sip-connector 19.8.3 → 20.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -138
- package/dist/@SipConnector-CZiURTVf.cjs +1 -0
- package/dist/{@SipConnector-BmkeKEDD.js → @SipConnector-D4DfiZRM.js} +1117 -977
- package/dist/ApiManager/@ApiManager.d.ts +0 -1
- package/dist/ApiManager/constants.d.ts +3 -8
- package/dist/ApiManager/eventNames.d.ts +15 -6
- package/dist/ApiManager/index.d.ts +0 -1
- package/dist/ApiManager/types.d.ts +0 -6
- package/dist/CallManager/@CallManager.d.ts +44 -15
- package/dist/CallManager/MCUSession.d.ts +0 -2
- package/dist/CallManager/RecvSession.d.ts +29 -0
- package/dist/CallManager/RemoteStreamsManager.d.ts +20 -5
- package/dist/CallManager/RoleManager.d.ts +31 -0
- package/dist/CallManager/eventNames.d.ts +9 -2
- package/dist/CallManager/index.d.ts +1 -2
- package/dist/CallManager/types.d.ts +29 -35
- package/dist/ConnectionManager/@ConnectionManager.d.ts +2 -2
- package/dist/ConnectionManager/ConfigurationManager.d.ts +6 -1
- package/dist/ConnectionManager/ConnectionFlow.d.ts +5 -4
- package/dist/ConnectionManager/SipOperations.d.ts +2 -2
- package/dist/ConnectionManager/UAFactory.d.ts +4 -4
- package/dist/SipConnector/@SipConnector.d.ts +4 -4
- package/dist/SipConnector/eventNames.d.ts +1 -1
- package/dist/SipConnectorFacade/@SipConnectorFacade.d.ts +0 -2
- package/dist/VideoSendingBalancer/__fixtures__/createMockTrack.d.ts +1 -1
- package/dist/__fixtures__/RTCPeerConnectionMock.d.ts +14 -18
- package/dist/__fixtures__/index.d.ts +4 -4
- package/dist/doMock.cjs +1 -1
- package/dist/doMock.js +134 -131
- package/dist/index.cjs +1 -1
- package/dist/index.js +156 -171
- package/dist/tools/__fixtures__/connectToServer.d.ts +15 -15
- package/dist/tools/__fixtures__/permissions.d.ts +2 -2
- package/dist/tools/__fixtures__/processRequest.d.ts +2 -2
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/sendOffer.d.ts +39 -0
- package/dist/utils/utils.d.ts +1 -1
- package/package.json +13 -5
- package/dist/@SipConnector-BHakZWEK.cjs +0 -1
- package/dist/CallManager/AbstractCallStrategy.d.ts +0 -54
- package/dist/CallManager/MCUCallStrategy.d.ts +0 -31
- package/dist/TransceiverManager/@TransceiverManager.d.ts +0 -70
- package/dist/TransceiverManager/index.d.ts +0 -1
- package/dist/TransceiverManager/types.d.ts +0 -11
|
@@ -26,7 +26,8 @@ export declare enum EHeader {
|
|
|
26
26
|
AVAILABLE_INCOMING_BITRATE = "X-WEBRTC-AVAILABLE-INCOMING-BITRATE",
|
|
27
27
|
AUDIO_TRACK_COUNT = "X-WEBRTC-AUDIO-TRACK-COUNT",
|
|
28
28
|
VIDEO_TRACK_COUNT = "X-WEBRTC-VIDEO-TRACK-COUNT",
|
|
29
|
-
TRACKS_DIRECTION = "X-WEBRTC-TRACKS-DIRECTION"
|
|
29
|
+
TRACKS_DIRECTION = "X-WEBRTC-TRACKS-DIRECTION",
|
|
30
|
+
AUDIO_ID = "X-WEBRTC-AUDIOID"
|
|
30
31
|
}
|
|
31
32
|
export declare enum EShareState {
|
|
32
33
|
AVAILABLE_SECOND_REMOTE_STREAM = "YOUCANRECEIVECONTENT",
|
|
@@ -44,8 +45,7 @@ export declare enum EContentTypeReceived {
|
|
|
44
45
|
PARTICIPANT_STATE = "application/vinteo.webrtc.partstate",
|
|
45
46
|
NOTIFY = "application/vinteo.webrtc.notify",
|
|
46
47
|
SHARE_STATE = "application/vinteo.webrtc.sharedesktop",
|
|
47
|
-
MAIN_CAM = "application/vinteo.webrtc.maincam"
|
|
48
|
-
RESTART = "application/vinteo.webrtc.restart"
|
|
48
|
+
MAIN_CAM = "application/vinteo.webrtc.maincam"
|
|
49
49
|
}
|
|
50
50
|
export declare enum EContentTypeSent {
|
|
51
51
|
CHANNELS = "application/vinteo.webrtc.channels",
|
|
@@ -75,8 +75,3 @@ export declare enum EUseLicense {
|
|
|
75
75
|
VIDEO = "VIDEO",
|
|
76
76
|
AUDIOPLUSPRESENTATION = "AUDIOPLUSPRESENTATION"
|
|
77
77
|
}
|
|
78
|
-
export declare enum ETracksDirection {
|
|
79
|
-
SENDRECV = "SENDRECV",
|
|
80
|
-
SENDONLY = "SENDONLY",
|
|
81
|
-
RECVONLY = "RECVONLY"
|
|
82
|
-
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { TypedEvents } from 'events-constructor';
|
|
2
2
|
import { EUseLicense, EEventsMainCAM } from './constants';
|
|
3
|
-
import { TChannels, TParametersModeratorsList, TParametersWebcast, TParametersConferenceParticipantTokenIssued
|
|
3
|
+
import { TChannels, TParametersModeratorsList, TParametersWebcast, TParametersConferenceParticipantTokenIssued } from './types';
|
|
4
4
|
export declare enum EEvent {
|
|
5
5
|
CHANNELS_NOTIFY = "channels:notify",
|
|
6
6
|
PARTICIPANT_ADDED_TO_LIST_MODERATORS = "participant:added-to-list-moderators",
|
|
7
7
|
PARTICIPANT_REMOVED_FROM_LIST_MODERATORS = "participant:removed-from-list-moderators",
|
|
8
8
|
PARTICIPANT_MOVE_REQUEST_TO_STREAM = "participant:move-request-to-stream",
|
|
9
9
|
PARTICIPANT_MOVE_REQUEST_TO_SPECTATORS = "participant:move-request-to-spectators",
|
|
10
|
+
PARTICIPANT_MOVE_REQUEST_TO_SPECTATORS_SYNTHETIC = "participant:move-request-to-spectators-synthetic",
|
|
11
|
+
PARTICIPANT_MOVE_REQUEST_TO_SPECTATORS_WITH_AUDIO_ID = "participant:move-request-to-spectators-with-audio-id",
|
|
10
12
|
PARTICIPANT_MOVE_REQUEST_TO_PARTICIPANTS = "participant:move-request-to-participants",
|
|
11
13
|
PARTICIPATION_ACCEPTING_WORD_REQUEST = "participation:accepting-word-request",
|
|
12
14
|
PARTICIPATION_CANCELLING_WORD_REQUEST = "participation:cancelling-word-request",
|
|
@@ -28,18 +30,26 @@ export declare enum EEvent {
|
|
|
28
30
|
AVAILABLE_SECOND_REMOTE_STREAM = "availableSecondRemoteStream",
|
|
29
31
|
NOT_AVAILABLE_SECOND_REMOTE_STREAM = "notAvailableSecondRemoteStream",
|
|
30
32
|
MUST_STOP_PRESENTATION = "mustStopPresentation",
|
|
31
|
-
NEW_DTMF = "newDTMF"
|
|
32
|
-
RESTART = "restart"
|
|
33
|
+
NEW_DTMF = "newDTMF"
|
|
33
34
|
}
|
|
34
|
-
export declare const EVENT_NAMES: readonly ["participation:accepting-word-request", "participation:cancelling-word-request", "participant:move-request-to-stream", "channels:notify", "conference:participant-token-issued", "account:changed", "account:deleted", "webcast:started", "webcast:stopped", "participant:added-to-list-moderators", "participant:removed-from-list-moderators", "participant:move-request-to-spectators", "participant:move-request-to-participants", "channels", "enterRoom", "shareState", "main-cam-control", "useLicense", "admin-start-main-cam", "admin-stop-main-cam", "admin-start-mic", "admin-stop-mic", "admin-force-sync-media-state", "availableSecondRemoteStream", "notAvailableSecondRemoteStream", "mustStopPresentation", "newDTMF"
|
|
35
|
+
export declare const EVENT_NAMES: readonly ["participation:accepting-word-request", "participation:cancelling-word-request", "participant:move-request-to-stream", "channels:notify", "conference:participant-token-issued", "account:changed", "account:deleted", "webcast:started", "webcast:stopped", "participant:added-to-list-moderators", "participant:removed-from-list-moderators", "participant:move-request-to-spectators", "participant:move-request-to-spectators-synthetic", "participant:move-request-to-spectators-with-audio-id", "participant:move-request-to-participants", "channels", "enterRoom", "shareState", "main-cam-control", "useLicense", "admin-start-main-cam", "admin-stop-main-cam", "admin-start-mic", "admin-stop-mic", "admin-force-sync-media-state", "availableSecondRemoteStream", "notAvailableSecondRemoteStream", "mustStopPresentation", "newDTMF"];
|
|
35
36
|
export type TEvent = (typeof EVENT_NAMES)[number];
|
|
36
37
|
export type TEventMap = {
|
|
37
38
|
'channels:notify': TChannels;
|
|
38
39
|
'participant:added-to-list-moderators': TParametersModeratorsList;
|
|
39
40
|
'participant:removed-from-list-moderators': TParametersModeratorsList;
|
|
40
41
|
'participant:move-request-to-stream': TParametersModeratorsList;
|
|
41
|
-
'participant:move-request-to-spectators': Record<string, never>;
|
|
42
42
|
'participant:move-request-to-participants': Record<string, never>;
|
|
43
|
+
'participant:move-request-to-spectators': {
|
|
44
|
+
isSynthetic: true;
|
|
45
|
+
} | {
|
|
46
|
+
isSynthetic: false;
|
|
47
|
+
audioId: string;
|
|
48
|
+
};
|
|
49
|
+
'participant:move-request-to-spectators-synthetic': Record<string, never>;
|
|
50
|
+
'participant:move-request-to-spectators-with-audio-id': {
|
|
51
|
+
audioId: string;
|
|
52
|
+
};
|
|
43
53
|
'participation:accepting-word-request': TParametersModeratorsList;
|
|
44
54
|
'participation:cancelling-word-request': TParametersModeratorsList;
|
|
45
55
|
'webcast:started': TParametersWebcast;
|
|
@@ -79,6 +89,5 @@ export type TEventMap = {
|
|
|
79
89
|
newDTMF: {
|
|
80
90
|
originator: string;
|
|
81
91
|
};
|
|
82
|
-
restart: TRestartData;
|
|
83
92
|
};
|
|
84
93
|
export type TEvents = TypedEvents<TEventMap>;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export { default as ApiManager } from './@ApiManager';
|
|
2
2
|
export { EContentTypeReceived, EContentTypeSent, EEventsMainCAM, EEventsMic, EEventsSyncMediaState, EHeader, EShareState, EUseLicense, } from './constants';
|
|
3
3
|
export type { TEvent as TApiEvent } from './eventNames';
|
|
4
|
-
export type { TRestartData } from './types';
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ETracksDirection } from './constants';
|
|
2
1
|
export declare enum ECMDNotify {
|
|
3
2
|
CHANNELS = "channels",
|
|
4
3
|
WEBCAST_STARTED = "WebcastStarted",
|
|
@@ -98,8 +97,3 @@ export type TOptionsInfoMediaState = {
|
|
|
98
97
|
export type TOptionsExtraHeaders = {
|
|
99
98
|
extraHeaders?: string[];
|
|
100
99
|
};
|
|
101
|
-
export type TRestartData = {
|
|
102
|
-
tracksDirection: ETracksDirection;
|
|
103
|
-
audioTrackCount: number;
|
|
104
|
-
videoTrackCount: number;
|
|
105
|
-
};
|
|
@@ -1,29 +1,58 @@
|
|
|
1
|
+
import { RTCSession } from '@krivega/jssip';
|
|
1
2
|
import { TEvents, TEventMap } from './eventNames';
|
|
2
|
-
import {
|
|
3
|
+
import { TStartCall, TCallConfiguration, TReplaceMediaStream, TAnswerToIncomingCall, TCallRoleSpectator } from './types';
|
|
3
4
|
declare class CallManager {
|
|
4
5
|
readonly events: TEvents;
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
protected isPendingCall: boolean;
|
|
7
|
+
protected isPendingAnswer: boolean;
|
|
8
|
+
protected rtcSession?: RTCSession;
|
|
9
|
+
protected readonly callConfiguration: TCallConfiguration;
|
|
10
|
+
private readonly mainRemoteStreamsManager;
|
|
11
|
+
private readonly recvRemoteStreamsManager;
|
|
12
|
+
private readonly roleManager;
|
|
13
|
+
private readonly mcuSession;
|
|
14
|
+
private recvSession?;
|
|
15
|
+
private disposeRecvSessionTrackListener?;
|
|
16
|
+
constructor();
|
|
7
17
|
get requested(): boolean;
|
|
8
|
-
get connection():
|
|
9
|
-
get isCallActive():
|
|
10
|
-
getEstablishedRTCSession:
|
|
18
|
+
get connection(): RTCPeerConnection | undefined;
|
|
19
|
+
get isCallActive(): boolean;
|
|
20
|
+
getEstablishedRTCSession: () => RTCSession | undefined;
|
|
11
21
|
on<T extends keyof TEventMap>(eventName: T, handler: (data: TEventMap[T]) => void): () => void;
|
|
12
22
|
onRace<T extends keyof TEventMap>(eventNames: T[], handler: (data: TEventMap[T], eventName: string) => void): () => void;
|
|
13
23
|
once<T extends keyof TEventMap>(eventName: T, handler: (data: TEventMap[T]) => void): () => void;
|
|
14
24
|
onceRace<T extends keyof TEventMap>(eventNames: T[], handler: (data: TEventMap[T], eventName: string) => void): () => void;
|
|
15
25
|
wait<T extends keyof TEventMap>(eventName: T): Promise<TEventMap[T]>;
|
|
16
26
|
off<T extends keyof TEventMap>(eventName: T, handler: (data: TEventMap[T]) => void): void;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
startCall: TStartCall;
|
|
28
|
+
endCall(): Promise<void>;
|
|
29
|
+
answerToIncomingCall: TAnswerToIncomingCall;
|
|
30
|
+
getCallConfiguration(): {
|
|
31
|
+
answer?: boolean;
|
|
32
|
+
number?: string;
|
|
33
|
+
};
|
|
34
|
+
getRemoteStreams(): MediaStream[];
|
|
35
|
+
setCallRoleParticipant(): void;
|
|
36
|
+
setCallRoleSpectatorSynthetic(): void;
|
|
37
|
+
setCallRoleSpectator(recvParams: TCallRoleSpectator['recvParams']): void;
|
|
38
|
+
replaceMediaStream(mediaStream: Parameters<TReplaceMediaStream>[0], options?: Parameters<TReplaceMediaStream>[1]): Promise<void>;
|
|
39
|
+
restartIce(options?: {
|
|
40
|
+
useUpdate?: boolean;
|
|
41
|
+
extraHeaders?: string[];
|
|
42
|
+
rtcOfferConstraints?: RTCOfferOptions;
|
|
43
|
+
sendEncodings?: RTCRtpEncodingParameters[];
|
|
44
|
+
degradationPreference?: RTCDegradationPreference;
|
|
45
|
+
}): Promise<boolean>;
|
|
46
|
+
private readonly reset;
|
|
26
47
|
private subscribeCallStatusChange;
|
|
27
48
|
private maybeTriggerCallStatus;
|
|
49
|
+
private subscribeMcuRemoteTrackEvents;
|
|
50
|
+
private addRemoteTrack;
|
|
51
|
+
private emitRemoteStreamsChanged;
|
|
52
|
+
private getActiveStreamsManager;
|
|
53
|
+
private attachRecvSessionTracks;
|
|
54
|
+
private startRecvSession;
|
|
55
|
+
private stopRecvSession;
|
|
56
|
+
private readonly onRoleChanged;
|
|
28
57
|
}
|
|
29
58
|
export default CallManager;
|
|
@@ -15,7 +15,6 @@ export declare class MCUSession implements IMCUSession {
|
|
|
15
15
|
startCall: IMCUSession['startCall'];
|
|
16
16
|
endCall(): Promise<void>;
|
|
17
17
|
answerToIncomingCall: IMCUSession['answerToIncomingCall'];
|
|
18
|
-
getRemoteTracks(): MediaStreamTrack[] | undefined;
|
|
19
18
|
replaceMediaStream(mediaStream: Parameters<IMCUSession['replaceMediaStream']>[0], options?: Parameters<IMCUSession['replaceMediaStream']>[1]): Promise<void>;
|
|
20
19
|
restartIce(options?: {
|
|
21
20
|
useUpdate?: boolean;
|
|
@@ -24,7 +23,6 @@ export declare class MCUSession implements IMCUSession {
|
|
|
24
23
|
sendEncodings?: RTCRtpEncodingParameters[];
|
|
25
24
|
degradationPreference?: RTCDegradationPreference;
|
|
26
25
|
}): Promise<boolean>;
|
|
27
|
-
addTransceiver(kind: 'audio' | 'video', options?: RTCRtpTransceiverInit): Promise<RTCRtpTransceiver>;
|
|
28
26
|
private readonly handleCall;
|
|
29
27
|
private subscribeToSessionEvents;
|
|
30
28
|
private unsubscribeFromSessionEvents;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
type TConferenceNumber = string;
|
|
2
|
+
type TSendOfferParams = {
|
|
3
|
+
quality: 'low' | 'medium' | 'high';
|
|
4
|
+
audioChannel: string;
|
|
5
|
+
};
|
|
6
|
+
type TConfig = Pick<TSendOfferParams, 'quality' | 'audioChannel'> & {
|
|
7
|
+
pcConfig?: RTCConfiguration;
|
|
8
|
+
};
|
|
9
|
+
export type TTools = {
|
|
10
|
+
sendOffer: (params: TSendOfferParams & {
|
|
11
|
+
conferenceNumber: TConferenceNumber;
|
|
12
|
+
}, offer: RTCSessionDescriptionInit) => Promise<RTCSessionDescription>;
|
|
13
|
+
};
|
|
14
|
+
declare class RecvSession {
|
|
15
|
+
private readonly config;
|
|
16
|
+
private readonly tools;
|
|
17
|
+
private readonly connection;
|
|
18
|
+
constructor(config: TConfig, tools: TTools);
|
|
19
|
+
get settings(): TConfig;
|
|
20
|
+
get peerConnection(): RTCPeerConnection;
|
|
21
|
+
close(): void;
|
|
22
|
+
call(conferenceNumber: TConferenceNumber): Promise<void>;
|
|
23
|
+
private createOffer;
|
|
24
|
+
private setRemoteDescription;
|
|
25
|
+
private waitForTracks;
|
|
26
|
+
private addTransceivers;
|
|
27
|
+
private addRecvOnlyTransceiver;
|
|
28
|
+
}
|
|
29
|
+
export default RecvSession;
|
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
export declare class RemoteStreamsManager {
|
|
2
|
-
private
|
|
2
|
+
private readonly participantGroups;
|
|
3
|
+
private readonly trackToGroup;
|
|
4
|
+
private readonly trackDisposers;
|
|
3
5
|
reset(): void;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
addTrack(track: MediaStreamTrack, { onRemoved, streamHint, }?: {
|
|
7
|
+
streamHint?: string;
|
|
8
|
+
onRemoved?: ({ trackId, participantId }: {
|
|
9
|
+
trackId: string;
|
|
10
|
+
participantId: string;
|
|
11
|
+
}) => void;
|
|
12
|
+
}): {
|
|
13
|
+
isAdded: true;
|
|
14
|
+
participantId: string;
|
|
15
|
+
} | {
|
|
16
|
+
isAdded: false;
|
|
17
|
+
};
|
|
18
|
+
removeTrack(trackId: string): boolean;
|
|
19
|
+
removeStaleTracks(participantId: string, keepTrackIds: string[]): boolean;
|
|
20
|
+
getStreams(participantId?: string): MediaStream[];
|
|
21
|
+
private disposeTrackListener;
|
|
22
|
+
private getParticipantGroups;
|
|
8
23
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { RemoteStreamsManager } from './RemoteStreamsManager';
|
|
2
|
+
import { TCallRole, TCallRoleParticipant, TCallRoleSpectatorSynthetic, TCallRoleSpectator } from './types';
|
|
3
|
+
type TOnRoleChanged = (params: {
|
|
4
|
+
previous: TCallRole;
|
|
5
|
+
next: TCallRole;
|
|
6
|
+
}) => void;
|
|
7
|
+
export declare class RoleManager {
|
|
8
|
+
private role;
|
|
9
|
+
private readonly mainManager;
|
|
10
|
+
private readonly recvManager;
|
|
11
|
+
private readonly onRoleChanged?;
|
|
12
|
+
constructor({ mainManager, recvManager, }: {
|
|
13
|
+
mainManager: RemoteStreamsManager;
|
|
14
|
+
recvManager: RemoteStreamsManager;
|
|
15
|
+
}, onRoleChanged?: TOnRoleChanged);
|
|
16
|
+
static hasParticipant(role: TCallRole): role is TCallRoleParticipant;
|
|
17
|
+
static hasSpectatorSynthetic(role: TCallRole): role is TCallRoleSpectatorSynthetic;
|
|
18
|
+
static hasSpectator(role: TCallRole): role is TCallRoleSpectator;
|
|
19
|
+
getRole(): TCallRole;
|
|
20
|
+
setCallRoleParticipant(): void;
|
|
21
|
+
setCallRoleSpectatorSynthetic(): void;
|
|
22
|
+
setCallRoleSpectator(recvParams: TCallRoleSpectator['recvParams']): void;
|
|
23
|
+
changeRole(next: TCallRole): void;
|
|
24
|
+
reset(): void;
|
|
25
|
+
getActiveManager(): RemoteStreamsManager;
|
|
26
|
+
hasParticipant(): boolean;
|
|
27
|
+
hasSpectatorSynthetic(): boolean;
|
|
28
|
+
hasSpectator(): boolean;
|
|
29
|
+
private setRole;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
@@ -34,7 +34,8 @@ export declare enum EEvent {
|
|
|
34
34
|
PEER_CONNECTION_CONFIRMED = "peerconnection:confirmed",
|
|
35
35
|
PEER_CONNECTION_ONTRACK = "peerconnection:ontrack",
|
|
36
36
|
ENDED_FROM_SERVER = "ended:fromserver",
|
|
37
|
-
CALL_STATUS_CHANGED = "call-status-changed"
|
|
37
|
+
CALL_STATUS_CHANGED = "call-status-changed",
|
|
38
|
+
REMOTE_STREAMS_CHANGED = "remote-streams-changed"
|
|
38
39
|
}
|
|
39
40
|
export declare enum Originator {
|
|
40
41
|
LOCAL = "local",
|
|
@@ -42,7 +43,7 @@ export declare enum Originator {
|
|
|
42
43
|
SYSTEM = "system"
|
|
43
44
|
}
|
|
44
45
|
export declare const SESSION_JSSIP_EVENT_NAMES: readonly ["peerconnection", "connecting", "sending", "progress", "accepted", "confirmed", "ended", "failed", "newInfo", "newDTMF", "presentation:start", "presentation:started", "presentation:end", "presentation:ended", "presentation:failed", "reinvite", "update", "refer", "replaces", "sdp", "icecandidate", "getusermediafailed", "peerconnection:createofferfailed", "peerconnection:createanswerfailed", "peerconnection:setlocaldescriptionfailed", "peerconnection:setremotedescriptionfailed"];
|
|
45
|
-
export declare const EVENT_NAMES: readonly ["peerconnection", "connecting", "sending", "progress", "accepted", "confirmed", "ended", "failed", "newInfo", "newDTMF", "presentation:start", "presentation:started", "presentation:end", "presentation:ended", "presentation:failed", "reinvite", "update", "refer", "replaces", "sdp", "icecandidate", "getusermediafailed", "peerconnection:createofferfailed", "peerconnection:createanswerfailed", "peerconnection:setlocaldescriptionfailed", "peerconnection:setremotedescriptionfailed", "peerconnection:confirmed", "peerconnection:ontrack", "ended:fromserver", "call-status-changed"];
|
|
46
|
+
export declare const EVENT_NAMES: readonly ["peerconnection", "connecting", "sending", "progress", "accepted", "confirmed", "ended", "failed", "newInfo", "newDTMF", "presentation:start", "presentation:started", "presentation:end", "presentation:ended", "presentation:failed", "reinvite", "update", "refer", "replaces", "sdp", "icecandidate", "getusermediafailed", "peerconnection:createofferfailed", "peerconnection:createanswerfailed", "peerconnection:setlocaldescriptionfailed", "peerconnection:setremotedescriptionfailed", "peerconnection:confirmed", "peerconnection:ontrack", "ended:fromserver", "call-status-changed", "remote-streams-changed"];
|
|
46
47
|
export type TEvent = (typeof EVENT_NAMES)[number];
|
|
47
48
|
export type TEventMap = {
|
|
48
49
|
peerconnection: {
|
|
@@ -85,5 +86,11 @@ export type TEventMap = {
|
|
|
85
86
|
'call-status-changed': {
|
|
86
87
|
isCallActive: boolean;
|
|
87
88
|
};
|
|
89
|
+
'remote-streams-changed': {
|
|
90
|
+
participantId: string;
|
|
91
|
+
changeType: 'added' | 'removed';
|
|
92
|
+
trackId: string;
|
|
93
|
+
streams: MediaStream[];
|
|
94
|
+
};
|
|
88
95
|
};
|
|
89
96
|
export type TEvents = TypedEvents<TEventMap>;
|
|
@@ -4,5 +4,4 @@ export type { TEventMap } from './eventNames';
|
|
|
4
4
|
export { EEvent as ECallEvent } from './eventNames';
|
|
5
5
|
export type { TEvent as TCallEvent, TEvents as TCallEvents } from './eventNames';
|
|
6
6
|
export { default as hasCanceledCallError } from './hasCanceledCallError';
|
|
7
|
-
export {
|
|
8
|
-
export type { TCustomError, TGetServerUrl } from './types';
|
|
7
|
+
export type { TCustomError, TGetUri } from './types';
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { RTCSession, UA } from '@krivega/jssip';
|
|
2
2
|
import { TContentHint } from '../PresentationManager';
|
|
3
3
|
import { Originator } from './eventNames';
|
|
4
|
-
|
|
4
|
+
import { TTools } from './RecvSession';
|
|
5
5
|
export type TOnAddedTransceiver = (transceiver: RTCRtpTransceiver, track: MediaStreamTrack, streams: MediaStream[]) => Promise<void>;
|
|
6
|
-
export type
|
|
6
|
+
export type TGetUri = (id: string) => string;
|
|
7
7
|
type TOptionsExtraHeaders = {
|
|
8
8
|
extraHeaders?: string[];
|
|
9
9
|
};
|
|
10
10
|
type TParamsAnswerToIncomingCall = {
|
|
11
11
|
mediaStream: MediaStream;
|
|
12
12
|
extraHeaders?: TOptionsExtraHeaders['extraHeaders'];
|
|
13
|
-
ontrack?: TOntrack;
|
|
14
13
|
iceServers?: RTCIceServer[];
|
|
15
14
|
directionVideo?: RTCRtpTransceiverDirection;
|
|
16
15
|
directionAudio?: RTCRtpTransceiverDirection;
|
|
@@ -37,43 +36,39 @@ export type TCallConfiguration = {
|
|
|
37
36
|
answer?: boolean;
|
|
38
37
|
number?: string;
|
|
39
38
|
};
|
|
40
|
-
export
|
|
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
|
-
degradationPreference?: RTCDegradationPreference;
|
|
66
|
-
}) => Promise<boolean>;
|
|
67
|
-
}
|
|
39
|
+
export type TCallRoleParticipant = {
|
|
40
|
+
type: 'participant';
|
|
41
|
+
};
|
|
42
|
+
export type TCallRoleSpectatorSynthetic = {
|
|
43
|
+
type: 'spectator_synthetic';
|
|
44
|
+
};
|
|
45
|
+
export type TCallRoleSpectator = {
|
|
46
|
+
type: 'spectator';
|
|
47
|
+
recvParams: {
|
|
48
|
+
audioId: string;
|
|
49
|
+
sendOffer: TTools['sendOffer'];
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
export type TCallRole = TCallRoleParticipant | TCallRoleSpectatorSynthetic | TCallRoleSpectator;
|
|
53
|
+
export type TStartCall = (ua: UA, getUri: TGetUri, params: TParamsCall) => Promise<RTCPeerConnection>;
|
|
54
|
+
export type TReplaceMediaStream = (mediaStream: MediaStream, options?: {
|
|
55
|
+
deleteExisting?: boolean;
|
|
56
|
+
addMissing?: boolean;
|
|
57
|
+
forceRenegotiation?: boolean;
|
|
58
|
+
contentHint?: TContentHint;
|
|
59
|
+
degradationPreference?: RTCDegradationPreference;
|
|
60
|
+
sendEncodings?: RTCRtpEncodingParameters[];
|
|
61
|
+
onAddedTransceiver?: TOnAddedTransceiver;
|
|
62
|
+
}) => Promise<void>;
|
|
63
|
+
export type TAnswerToIncomingCall = (extractIncomingRTCSession: () => RTCSession, params: TParamsAnswerToIncomingCall) => Promise<RTCPeerConnection>;
|
|
68
64
|
export interface IMCUSession {
|
|
69
65
|
readonly connection: RTCPeerConnection | undefined;
|
|
70
66
|
readonly isCallActive: boolean;
|
|
71
67
|
getEstablishedRTCSession: () => RTCSession | undefined;
|
|
72
|
-
startCall:
|
|
68
|
+
startCall: TStartCall;
|
|
73
69
|
endCall: () => Promise<void>;
|
|
74
70
|
answerToIncomingCall: (incomingRTCSession: RTCSession, params: TParamsAnswerToIncomingCall) => Promise<RTCPeerConnection>;
|
|
75
|
-
|
|
76
|
-
replaceMediaStream: ICallStrategy['replaceMediaStream'];
|
|
71
|
+
replaceMediaStream: TReplaceMediaStream;
|
|
77
72
|
restartIce: (options?: {
|
|
78
73
|
useUpdate?: boolean;
|
|
79
74
|
extraHeaders?: string[];
|
|
@@ -81,6 +76,5 @@ export interface IMCUSession {
|
|
|
81
76
|
sendEncodings?: RTCRtpEncodingParameters[];
|
|
82
77
|
degradationPreference?: RTCDegradationPreference;
|
|
83
78
|
}) => Promise<boolean>;
|
|
84
|
-
addTransceiver: (kind: 'audio' | 'video', options?: RTCRtpTransceiverInit) => Promise<RTCRtpTransceiver>;
|
|
85
79
|
}
|
|
86
80
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { default as SipOperations, TParametersCheckTelephony } from './SipOperations';
|
|
2
2
|
import { RegisteredEvent, UA, UnRegisteredEvent, WebSocketInterface } from '@krivega/jssip';
|
|
3
|
-
import {
|
|
3
|
+
import { TGetUri } from '../CallManager';
|
|
4
4
|
import { TJsSIP } from '../types';
|
|
5
5
|
import { TConnect, TConnectionConfigurationWithUa, TParametersConnection, TSet } from './ConnectionFlow';
|
|
6
6
|
import { TEventMap, TEvents } from './eventNames';
|
|
@@ -48,7 +48,7 @@ export default class ConnectionManager {
|
|
|
48
48
|
isConfigured(): boolean;
|
|
49
49
|
getConnectionConfiguration: () => import('./ConfigurationManager').IConnectionConfiguration | undefined;
|
|
50
50
|
destroy(): void;
|
|
51
|
-
|
|
51
|
+
getUri: TGetUri;
|
|
52
52
|
readonly getUaProtected: () => UA;
|
|
53
53
|
private readonly getUa;
|
|
54
54
|
private readonly connectWithProcessError;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UA } from '@krivega/jssip';
|
|
2
2
|
export interface IConnectionConfiguration {
|
|
3
|
+
sipServerIp: string;
|
|
3
4
|
sipServerUrl: string;
|
|
4
5
|
displayName: string;
|
|
5
6
|
register?: boolean;
|
|
@@ -38,7 +39,11 @@ export default class ConfigurationManager {
|
|
|
38
39
|
*/
|
|
39
40
|
isRegister(): boolean;
|
|
40
41
|
/**
|
|
41
|
-
* Получает SIP сервер
|
|
42
|
+
* Получает SIP сервер IP из конфигурации
|
|
43
|
+
*/
|
|
44
|
+
getSipServerIp(): string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Получает SIP сервер URL (WebSocket) из конфигурации
|
|
42
47
|
*/
|
|
43
48
|
getSipServerUrl(): string | undefined;
|
|
44
49
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UA, WebSocketInterface } from '@krivega/jssip';
|
|
2
|
-
import {
|
|
2
|
+
import { TGetUri } from '../CallManager';
|
|
3
3
|
import { TJsSIP } from '../types';
|
|
4
4
|
import { default as ConnectionStateMachine } from './ConnectionStateMachine';
|
|
5
5
|
import { TEvents } from './eventNames';
|
|
@@ -9,8 +9,8 @@ export type TOptionsExtraHeaders = {
|
|
|
9
9
|
extraHeaders?: string[];
|
|
10
10
|
};
|
|
11
11
|
export type TParametersConnection = TOptionsExtraHeaders & {
|
|
12
|
+
sipServerIp: string;
|
|
12
13
|
sipServerUrl: string;
|
|
13
|
-
sipWebSocketServerURL: string;
|
|
14
14
|
displayName: string;
|
|
15
15
|
register?: boolean;
|
|
16
16
|
user?: string;
|
|
@@ -23,6 +23,7 @@ export type TParametersConnection = TOptionsExtraHeaders & {
|
|
|
23
23
|
connectionRecoveryMaxInterval?: number;
|
|
24
24
|
};
|
|
25
25
|
export type TConnectionConfiguration = {
|
|
26
|
+
sipServerIp: string;
|
|
26
27
|
sipServerUrl: string;
|
|
27
28
|
displayName: string;
|
|
28
29
|
register?: boolean;
|
|
@@ -49,7 +50,7 @@ interface IDependencies {
|
|
|
49
50
|
getConnectionConfiguration: () => TConnectionConfiguration | undefined;
|
|
50
51
|
setConnectionConfiguration: (config: TConnectionConfiguration | undefined) => void;
|
|
51
52
|
updateConnectionConfiguration: <K extends keyof TConnectionConfiguration>(key: K, value: TConnectionConfiguration[K]) => void;
|
|
52
|
-
|
|
53
|
+
setGetUri: (getUri: TGetUri) => void;
|
|
53
54
|
setSocket: (socket: WebSocketInterface) => void;
|
|
54
55
|
}
|
|
55
56
|
export default class ConnectionFlow {
|
|
@@ -64,7 +65,7 @@ export default class ConnectionFlow {
|
|
|
64
65
|
private readonly getConnectionConfiguration;
|
|
65
66
|
private readonly setConnectionConfiguration;
|
|
66
67
|
private readonly updateConnectionConfiguration;
|
|
67
|
-
private readonly
|
|
68
|
+
private readonly setGetUri;
|
|
68
69
|
private readonly setSocket;
|
|
69
70
|
constructor(dependencies: IDependencies);
|
|
70
71
|
connect: TConnect;
|
|
@@ -2,8 +2,8 @@ import { UA, URI } from '@krivega/jssip';
|
|
|
2
2
|
import { default as UAFactory } from './UAFactory';
|
|
3
3
|
export type TParametersCheckTelephony = {
|
|
4
4
|
displayName: string;
|
|
5
|
+
sipServerIp: string;
|
|
5
6
|
sipServerUrl: string;
|
|
6
|
-
sipWebSocketServerURL: string;
|
|
7
7
|
userAgent?: string;
|
|
8
8
|
remoteAddress?: string;
|
|
9
9
|
extraHeaders?: string[];
|
|
@@ -27,6 +27,6 @@ export default class SipOperations {
|
|
|
27
27
|
/**
|
|
28
28
|
* Проверяет доступность телефонии, создавая временное соединение
|
|
29
29
|
*/
|
|
30
|
-
checkTelephony({ userAgent, displayName,
|
|
30
|
+
checkTelephony({ userAgent, displayName, sipServerIp, sipServerUrl, remoteAddress, extraHeaders, }: TParametersCheckTelephony): Promise<void>;
|
|
31
31
|
}
|
|
32
32
|
export {};
|
|
@@ -4,7 +4,7 @@ export type TUAConfiguration = {
|
|
|
4
4
|
configuration: UAConfigurationParams;
|
|
5
5
|
helpers: {
|
|
6
6
|
socket: WebSocketInterface;
|
|
7
|
-
|
|
7
|
+
getUri: (id: string) => string;
|
|
8
8
|
};
|
|
9
9
|
};
|
|
10
10
|
export type TCreateUAParameters = UAConfigurationParams & {
|
|
@@ -12,9 +12,9 @@ export type TCreateUAParameters = UAConfigurationParams & {
|
|
|
12
12
|
extraHeaders?: string[];
|
|
13
13
|
};
|
|
14
14
|
type TParametersCreateUaConfiguration = {
|
|
15
|
-
sipWebSocketServerURL: string;
|
|
16
|
-
displayName: string;
|
|
17
15
|
sipServerUrl: string;
|
|
16
|
+
displayName: string;
|
|
17
|
+
sipServerIp: string;
|
|
18
18
|
user?: string;
|
|
19
19
|
register?: boolean;
|
|
20
20
|
password?: string;
|
|
@@ -31,7 +31,7 @@ export default class UAFactory {
|
|
|
31
31
|
private static validateParametersConnection;
|
|
32
32
|
private static resolveAuthorizationUser;
|
|
33
33
|
private static buildExtraHeaders;
|
|
34
|
-
createConfiguration({ user, password,
|
|
34
|
+
createConfiguration({ user, password, sipServerUrl, displayName, sipServerIp, register, sessionTimers, registerExpires, // 5 minutes in sec
|
|
35
35
|
connectionRecoveryMinInterval, connectionRecoveryMaxInterval, userAgent, }: TParametersCreateUaConfiguration): TUAConfiguration;
|
|
36
36
|
createUA({ remoteAddress, extraHeaders, ...parameters }: TCreateUAParameters): UA;
|
|
37
37
|
/**
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { ApiManager } from '../ApiManager';
|
|
2
2
|
import { AutoConnectorManager, IAutoConnectorOptions } from '../AutoConnectorManager';
|
|
3
|
-
import { CallManager,
|
|
3
|
+
import { CallManager, TGetUri } from '../CallManager';
|
|
4
4
|
import { ConnectionManager } from '../ConnectionManager';
|
|
5
5
|
import { ConnectionQueueManager } from '../ConnectionQueueManager';
|
|
6
6
|
import { IncomingCallManager } from '../IncomingCallManager';
|
|
7
7
|
import { PresentationManager, TContentHint, TOnAddedTransceiver } from '../PresentationManager';
|
|
8
8
|
import { StatsManager } from '../StatsManager';
|
|
9
|
-
import { TransceiverManager } from '../TransceiverManager';
|
|
10
9
|
import { VideoSendingBalancerManager } from '../VideoSendingBalancerManager';
|
|
11
10
|
import { TJsSIP } from '../types';
|
|
12
11
|
import { IBalancerOptions } from '../VideoSendingBalancer';
|
|
@@ -22,7 +21,6 @@ declare class SipConnector {
|
|
|
22
21
|
readonly presentationManager: PresentationManager;
|
|
23
22
|
readonly statsManager: StatsManager;
|
|
24
23
|
readonly videoSendingBalancerManager: VideoSendingBalancerManager;
|
|
25
|
-
readonly transceiverManager: TransceiverManager;
|
|
26
24
|
private readonly preferredMimeTypesVideoCodecs?;
|
|
27
25
|
private readonly excludeMimeTypesVideoCodecs?;
|
|
28
26
|
constructor({ JsSIP }: {
|
|
@@ -61,7 +59,7 @@ declare class SipConnector {
|
|
|
61
59
|
checkTelephony: ConnectionManager['checkTelephony'];
|
|
62
60
|
isConfigured: () => boolean;
|
|
63
61
|
getConnectionConfiguration: () => import('../ConnectionManager/ConfigurationManager').IConnectionConfiguration | undefined;
|
|
64
|
-
|
|
62
|
+
getUri: TGetUri;
|
|
65
63
|
startAutoConnect: AutoConnectorManager['start'];
|
|
66
64
|
stopAutoConnect: AutoConnectorManager['stop'];
|
|
67
65
|
call: (params: Parameters<CallManager["startCall"]>[2]) => Promise<RTCPeerConnection>;
|
|
@@ -108,6 +106,8 @@ declare class SipConnector {
|
|
|
108
106
|
askPermissionToStartPresentationP2P(...args: Parameters<ApiManager['askPermissionToStartPresentationP2P']>): Promise<void>;
|
|
109
107
|
askPermissionToStartPresentation(...args: Parameters<ApiManager['askPermissionToStartPresentation']>): Promise<void>;
|
|
110
108
|
askPermissionToEnableCam(...args: Parameters<ApiManager['askPermissionToEnableCam']>): Promise<void>;
|
|
109
|
+
private subscribeChangeRole;
|
|
110
|
+
private readonly sendOffer;
|
|
111
111
|
private setCodecPreferences;
|
|
112
112
|
private subscribe;
|
|
113
113
|
private readonly bridgeEvents;
|
|
@@ -7,7 +7,7 @@ import { TEventMap as TIncomingCallManagerEventMap } from '../IncomingCallManage
|
|
|
7
7
|
import { TEventMap as TPresentationManagerEventMap } from '../PresentationManager/eventNames';
|
|
8
8
|
import { TEventMap as TStatsManagerEventMap } from '../StatsPeerConnection/eventNames';
|
|
9
9
|
import { TEventMap as TVideoBalancerManagerEventMap } from '../VideoSendingBalancerManager/eventNames';
|
|
10
|
-
export declare const EVENT_NAMES: readonly ("auto-connect:before-attempt" | "auto-connect:success" | "auto-connect:failed-all-attempts" | "auto-connect:cancelled-attempts" | "auto-connect:changed-attempt-status" | "auto-connect:stop-attempts-by-error" | "auto-connect:limit-reached-attempts" | "connection:connecting" | "connection:connected" | "connection:disconnected" | "connection:disconnecting" | "connection:newRTCSession" | "connection:registered" | "connection:unregistered" | "connection:registrationFailed" | "connection:newMessage" | "connection:sipEvent" | "connection:connect-started" | "connection:connect-succeeded" | "connection:connected-with-configuration" | "connection:connect-failed" | "connection:connect-parameters-resolve-success" | "connection:connect-parameters-resolve-failed" | "call:peerconnection" | "call:connecting" | "call:sending" | "call:progress" | "call:accepted" | "call:confirmed" | "call:ended" | "call:failed" | "call:newDTMF" | "call:newInfo" | "call:reinvite" | "call:update" | "call:refer" | "call:replaces" | "call:sdp" | "call:icecandidate" | "call:getusermediafailed" | "call:peerconnection:createofferfailed" | "call:peerconnection:createanswerfailed" | "call:peerconnection:setlocaldescriptionfailed" | "call:peerconnection:setremotedescriptionfailed" | "call:presentation:start" | "call:presentation:started" | "call:presentation:end" | "call:presentation:ended" | "call:presentation:failed" | "call:peerconnection:confirmed" | "call:peerconnection:ontrack" | "call:ended:fromserver" | "call:call-status-changed" | "api:channels:notify" | "api:participant:added-to-list-moderators" | "api:participant:removed-from-list-moderators" | "api:participant:move-request-to-stream" | "api:participant:move-request-to-spectators" | "api:participant:move-request-to-
|
|
10
|
+
export declare const EVENT_NAMES: readonly ("auto-connect:before-attempt" | "auto-connect:success" | "auto-connect:failed-all-attempts" | "auto-connect:cancelled-attempts" | "auto-connect:changed-attempt-status" | "auto-connect:stop-attempts-by-error" | "auto-connect:limit-reached-attempts" | "connection:connecting" | "connection:connected" | "connection:disconnected" | "connection:disconnecting" | "connection:newRTCSession" | "connection:registered" | "connection:unregistered" | "connection:registrationFailed" | "connection:newMessage" | "connection:sipEvent" | "connection:connect-started" | "connection:connect-succeeded" | "connection:connected-with-configuration" | "connection:connect-failed" | "connection:connect-parameters-resolve-success" | "connection:connect-parameters-resolve-failed" | "call:peerconnection" | "call:connecting" | "call:sending" | "call:progress" | "call:accepted" | "call:confirmed" | "call:ended" | "call:failed" | "call:newDTMF" | "call:newInfo" | "call:reinvite" | "call:update" | "call:refer" | "call:replaces" | "call:sdp" | "call:icecandidate" | "call:getusermediafailed" | "call:peerconnection:createofferfailed" | "call:peerconnection:createanswerfailed" | "call:peerconnection:setlocaldescriptionfailed" | "call:peerconnection:setremotedescriptionfailed" | "call:presentation:start" | "call:presentation:started" | "call:presentation:end" | "call:presentation:ended" | "call:presentation:failed" | "call:peerconnection:confirmed" | "call:peerconnection:ontrack" | "call:ended:fromserver" | "call:call-status-changed" | "call:remote-streams-changed" | "api:channels:notify" | "api:participant:added-to-list-moderators" | "api:participant:removed-from-list-moderators" | "api:participant:move-request-to-stream" | "api:participant:move-request-to-participants" | "api:participant:move-request-to-spectators" | "api:participant:move-request-to-spectators-synthetic" | "api:participant:move-request-to-spectators-with-audio-id" | "api:participation:accepting-word-request" | "api:participation:cancelling-word-request" | "api:webcast:started" | "api:webcast:stopped" | "api:account:changed" | "api:account:deleted" | "api:conference:participant-token-issued" | "api:channels" | "api:enterRoom" | "api:shareState" | "api:main-cam-control" | "api:useLicense" | "api:admin-start-main-cam" | "api:admin-stop-main-cam" | "api:admin-start-mic" | "api:admin-stop-mic" | "api:admin-force-sync-media-state" | "api:availableSecondRemoteStream" | "api:notAvailableSecondRemoteStream" | "api:mustStopPresentation" | "api:newDTMF" | "incoming-call:incomingCall" | "incoming-call:declinedIncomingCall" | "incoming-call:terminatedIncomingCall" | "incoming-call:failedIncomingCall" | "presentation:presentation:start" | "presentation:presentation:started" | "presentation:presentation:end" | "presentation:presentation:ended" | "presentation:presentation:failed" | "stats:collected" | "video-balancer:balancing-scheduled" | "video-balancer:balancing-started" | "video-balancer:balancing-stopped" | "video-balancer:parameters-updated")[];
|
|
11
11
|
export type TEvent = (typeof EVENT_NAMES)[number];
|
|
12
12
|
type PrefixedEventMap<T extends Record<string, unknown>, Prefix extends string> = {
|
|
13
13
|
[K in keyof T as `${Prefix}:${string & K}`]: T[K];
|