opensips-js 0.1.46 → 0.1.47

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/dist/index.d.ts CHANGED
@@ -394,6 +394,8 @@ declare type changeIsDNDListener = (value: boolean) => void
394
394
 
395
395
  declare type changeIsMutedListener = (value: boolean) => void
396
396
 
397
+ declare type changeMsrpSessionListener = (session: IMessage | null) => void
398
+
397
399
  declare type changeMuteWhenJoinListener = (value: boolean) => void
398
400
 
399
401
  declare type changeNoiseReductionStateListener = (event: boolean) => void
@@ -587,8 +589,52 @@ declare const MODULES: {
587
589
 
588
590
  declare type Modules = AudioModuleName | VideoModuleName | MSRPModuleName
589
591
 
592
+ declare type msrpConversationCreatedListener = (payload: {
593
+ conversationKey: string
594
+ conversation: MSRPConversationState
595
+ }) => void
596
+
597
+ declare type msrpConversationRemovedListener = (payload: { conversationKey: string }) => void
598
+
599
+ /**
600
+ * Protocol-level conversation state owned by MSRPModule.
601
+ *
602
+ * Intentionally does NOT carry a `messages` array - the module is a pure
603
+ * pipe for chat history. Live messages are emitted via `msrpMessageAdded`
604
+ * and historical messages from `m.sync` come through the
605
+ * `messagesByConversation` field of the `msrpSyncCompleted` payload.
606
+ * The consumer (e.g. a Vue composable) is responsible for collecting them
607
+ * into whatever data structure it needs and for downstream concerns like
608
+ * deduplication, reaction aggregation and receipt application.
609
+ */
610
+ declare interface MSRPConversationState {
611
+ conversationKey: string;
612
+ creator: string | null;
613
+ members: Set<string>;
614
+ memberRoles: Map<string, MSRPMemberRole>;
615
+ currentUserRole: MSRPMemberRole;
616
+ currentUserStatus: MSRPMembership | null;
617
+ state_events: {
618
+ [key: string]: {
619
+ [stateKey: string]: any;
620
+ };
621
+ };
622
+ created_at: number;
623
+ updated_at: number;
624
+ status?: string;
625
+ }
626
+
627
+ declare type msrpConversationUpdatedListener = (payload: {
628
+ conversationKey: string
629
+ patch: Partial<MSRPConversationState>
630
+ }) => void
631
+
590
632
  declare type MSRPInitializingListener = (sessionId: string | undefined) => void
591
633
 
634
+ declare type MSRPMemberRole = 'in_charge' | 'manager' | 'assigned';
635
+
636
+ declare type MSRPMembership = 'join' | 'leave' | 'invite' | 'ban';
637
+
592
638
  declare class MSRPMessage {
593
639
  protocol: string
594
640
  ident: string
@@ -604,6 +650,11 @@ declare class MSRPMessage {
604
650
  toString(): string
605
651
  }
606
652
 
653
+ declare type msrpMessageAddedListener = (payload: {
654
+ conversationKey: string
655
+ message: any
656
+ }) => void
657
+
607
658
  declare type MSRPMessageEventType = {
608
659
  message: MSRPMessage,
609
660
  session: MSRPSessionExtended
@@ -611,30 +662,177 @@ declare type MSRPMessageEventType = {
611
662
 
612
663
  declare type MSRPMessageListener = (event: MSRPMessageEventType) => void;
613
664
 
665
+ declare type MSRPMessageStatus = 'pending' | 'sent' | 'delivered' | 'read' | 'failed';
666
+
614
667
  declare class MSRPModule {
615
668
  private context;
616
- private activeMessages;
617
- private extendedMessages;
618
- private msrpHistory;
669
+ private msrpSession;
670
+ private extendedSession;
619
671
  private isMSRPInitializingValue;
672
+ private conversationsMap;
673
+ private pendingUploads;
674
+ private pendingFileAccessRequests;
675
+ private uploadRequestTimeoutMs;
676
+ private fileAccessTimeoutMs;
677
+ private typingKeepAliveInterval;
678
+ private typingKeepAliveConversationKey;
679
+ private typingKeepAliveIntervalMs;
620
680
  constructor(context: any);
621
681
  get isMSRPInitializing(): boolean;
622
- get getActiveMessages(): {
623
- [key: string]: IMessage;
682
+ get getMsrpSession(): IMessage;
683
+ get hasActiveSession(): boolean;
684
+ get conversations(): {
685
+ [key: string]: MSRPConversationState;
624
686
  };
625
- msrpAnswer(callId: string): void;
687
+ msrpAnswer(_callId: string): void;
626
688
  updateMSRPSession(value: IMessage): void;
627
- private addMMSRPSession;
689
+ private setMSRPSession;
628
690
  private addMSRPMessage;
629
- messageTerminate(callId: string): void;
691
+ messageTerminate(_callId: string): void;
630
692
  private addMessageSession;
631
693
  private triggerMSRPListener;
632
- private removeMMSRPSession;
633
- private activeMessageListRemove;
694
+ private clearMSRPSession;
634
695
  private newMSRPSessionCallback;
635
696
  private setIsMSRPInitializing;
636
- initMSRP(target: string, body: string, options: any): void;
637
- sendMSRP(msrpSessionId: string, body: string): void;
697
+ private getUserUri;
698
+ /**
699
+ * Open an MSRP session for the currently logged-in user. The SIP
700
+ * identity is resolved automatically from the OpenSIPSJS
701
+ * configuration, so the caller never has to pass it. Use this when
702
+ * the session is intended to act as a long-lived transport pipe and
703
+ * the first payload will be sent later through one of the higher-level
704
+ * actions (e.g. `sendCreateConversationMessage`).
705
+ */
706
+ initMSRP(options?: any): void;
707
+ /**
708
+ * Open an MSRP session and push `body` as the first MSRP frame the
709
+ * moment the session goes active. Use this for the legacy
710
+ * "compose-and-send" flow where the first message is known at the
711
+ * time the session is opened.
712
+ */
713
+ initMSRPAndSendMessage(target: string, body: string, options?: any): void;
714
+ /**
715
+ * Public raw send - kept for backward-compat with the old multi-session API.
716
+ * Ignores the passed callId/sessionId because we only ever hold one session.
717
+ */
718
+ sendMSRP(_msrpSessionId: string, body: string): void;
719
+ /**
720
+ * Safe wrapper around session.sendMSRP. Returns true when the message was
721
+ * handed off to the session; false when there is no active session or the
722
+ * underlying send threw. On failure the stored session is cleared so the
723
+ * next send attempt does not silently drop traffic on a half-dead session.
724
+ */
725
+ safeSendMSRP(body: string): boolean;
726
+ private buildCreateConversationEvent;
727
+ private buildTextMessageEvent;
728
+ private buildMediaMessageEvent;
729
+ private buildMemberEvent;
730
+ private buildCloseConversationEvent;
731
+ private buildReactionEvent;
732
+ private buildTypingEvent;
733
+ private buildReadReceiptEvent;
734
+ /**
735
+ * Create a new conversation by inviting one or more SIP URIs.
736
+ * Accepts plain numbers/usernames and rewrites them into full SIP URIs
737
+ * against the domain OpenSIPSJS was initialized with.
738
+ */
739
+ sendCreateConversationMessage(targetSip: string | string[]): boolean;
740
+ sendTextMessage(conversationKey: string, text: string): boolean;
741
+ sendMediaMessage(conversationKey: string, uploadResult: MSRPUploadResult, caption?: string): boolean;
742
+ sendReaction(conversationKey: string, targetEventId: string, emoji: string): boolean;
743
+ sendTypingIndicator(conversationKey: string, isTyping: boolean): boolean;
744
+ /**
745
+ * Start an automatic typing keep-alive loop for `conversationKey`. While
746
+ * active, a typing=true event is re-sent every `typingKeepAliveIntervalMs`
747
+ * so the remote side does not time out the indicator. Calling this with a
748
+ * different conversationKey or calling `stopTypingKeepAlive()` cancels
749
+ * any in-flight loop.
750
+ */
751
+ startTypingKeepAlive(conversationKey: string): void;
752
+ stopTypingKeepAlive(sendStop?: boolean): void;
753
+ /**
754
+ * Send a read receipt for `lastEventId` in `conversationKey`. The
755
+ * caller is responsible for resolving which event_id represents the
756
+ * "last seen" message because the module no longer stores chat history.
757
+ */
758
+ sendReadReceipt(conversationKey: string, lastEventId: string): boolean;
759
+ /**
760
+ * Close a conversation. Only callers with role 'in_charge' or 'manager'
761
+ * are allowed by the backend.
762
+ */
763
+ closeConversation(conversationKey: string, reason?: string, cause?: string): boolean;
764
+ /**
765
+ * Change another member's role inside a conversation. The current user
766
+ * must be 'in_charge' or 'manager'.
767
+ */
768
+ changeMemberRole(conversationKey: string, targetUri: string, newRole: MSRPMemberRole): boolean;
769
+ acceptInvite(conversationKey: string): boolean;
770
+ rejectInvite(conversationKey: string): boolean;
771
+ leaveConversation(conversationKey: string): boolean;
772
+ /**
773
+ * Ask the server for a presigned upload URL via MSRP. Resolves with the
774
+ * upload metadata once the matching `m.upload.response` arrives, or
775
+ * rejects after `uploadRequestTimeoutMs` if no response is received.
776
+ */
777
+ requestUploadUrl(conversationKey: string, filename: string, mimeType: string, fileSize: number): Promise<MSRPUploadResult>;
778
+ /**
779
+ * Ask the server for a one-shot download URL for a previously-uploaded
780
+ * file. Resolves with the download URL, rejects on timeout or explicit
781
+ * server error.
782
+ */
783
+ requestFileAccess(conversationKey: string, eventId: string): Promise<string>;
784
+ /**
785
+ * High-level helper: request a presigned URL, POST the file to it, then
786
+ * send the resulting media message into the conversation in one go.
787
+ */
788
+ uploadFile(conversationKey: string, file: File, caption?: string): Promise<MSRPUploadResult>;
789
+ /**
790
+ * Parse a raw MSRP `newMessage` payload and dispatch it to the right
791
+ * conversation-state mutator. Outgoing messages and non-JSON payloads
792
+ * are ignored so the rest of the pipeline stays pure.
793
+ */
794
+ private processIncomingMSRPMessage;
795
+ private handleIncomingEvent;
796
+ private handleIncomingSync;
797
+ private handleIncomingConversationCreate;
798
+ private handleIncomingConversationMessage;
799
+ private handleIncomingConversationClosed;
800
+ private handleIncomingReceipt;
801
+ private handleIncomingTyping;
802
+ private handleIncomingReaction;
803
+ private handleIncomingConversationMember;
804
+ private handleIncomingUploadResponse;
805
+ private handleIncomingFileAccessResponse;
806
+ private upsertConversationState;
807
+ /**
808
+ * Make a shallow snapshot of a conversation that is safe to hand off
809
+ * to an external consumer (e.g. a Vue composable).
810
+ *
811
+ * The mutable top-level collections (members, memberRoles,
812
+ * state_events) are cloned so subsequent internal mutations by the
813
+ * module cannot leak into the consumer's state. There is no
814
+ * `messages` field - chat history is owned by the consumer.
815
+ */
816
+ private snapshotConversation;
817
+ /**
818
+ * Snapshot the whole conversations map - used only for the bulk
819
+ * `msrpSyncCompleted` emit.
820
+ */
821
+ private snapshotConversationsMap;
822
+ isConversationClosed(conversation: MSRPConversationState | undefined | null): boolean;
823
+ /**
824
+ * Extract the conversationKey from either a string or an event/conversation object.
825
+ */
826
+ private conversationKeyOf;
827
+ /**
828
+ * Extract the user-part of a SIP URI, e.g. sip:103@example.com -> 103.
829
+ */
830
+ extractSipUser(sipUri: string | null | undefined): string | null;
831
+ /**
832
+ * Best-effort human-readable name for any URI we may encounter
833
+ * (SIP / WhatsApp / SMS / GreenAPI).
834
+ */
835
+ extractDisplayName(uri: string | null | undefined): string;
638
836
  }
639
837
 
640
838
  declare type MSRPModuleName = typeof MODULES.MSRP
@@ -653,6 +851,22 @@ declare interface MSRPOptions_2 extends AnswerOptions {
653
851
  fromDisplayName?: string;
654
852
  }
655
853
 
854
+ declare type msrpReactionChangedListener = (payload: {
855
+ conversationKey: string
856
+ eventId: string
857
+ emoji: string
858
+ action: 'add' | 'remove'
859
+ sender: string
860
+ updatedAt: number
861
+ }) => void
862
+
863
+ declare type msrpReceiptChangedListener = (payload: {
864
+ conversationKey: string
865
+ eventId: string
866
+ status: MSRPMessageStatus
867
+ updatedAt: number
868
+ }) => void
869
+
656
870
  declare class MSRPSession extends EventEmitter {
657
871
  _ua: UAExtendedInterface
658
872
  id: any
@@ -822,6 +1036,29 @@ declare interface MSRPSessionExtended extends MSRPSession_2 {
822
1036
 
823
1037
  declare type MSRPSessionListener = IncomingMSRPSessionListener | OutgoingMSRPSessionListener;
824
1038
 
1039
+ declare type msrpSyncCompletedListener = (payload: {
1040
+ conversations: { [key: string]: MSRPConversationState }
1041
+ messagesByConversation: { [key: string]: any[] }
1042
+ }) => void
1043
+
1044
+ declare type msrpTypingListener = (payload: {
1045
+ conversationKey: string
1046
+ sender: string
1047
+ isTyping: boolean
1048
+ }) => void
1049
+
1050
+ declare interface MSRPUploadResult {
1051
+ upload_url: string;
1052
+ expires_in?: number;
1053
+ mime_type: string;
1054
+ request_id: string;
1055
+ filename?: string;
1056
+ preview_url?: string;
1057
+ icon_url?: string;
1058
+ transcription?: string;
1059
+ media_type?: string;
1060
+ }
1061
+
825
1062
  declare type NoiseReductionMode = 'disabled' | 'enabled' | 'dynamic'
826
1063
 
827
1064
  declare interface NoiseReductionOptions {
@@ -881,6 +1118,16 @@ declare interface OpenSIPSEventMap extends UAEventMap {
881
1118
  connectionStateChange: connectionStateChangeListener
882
1119
  newMSRPMessage: MSRPMessageListener
883
1120
  newMSRPSession: MSRPSessionListener
1121
+ // MSRP - granular conversation events
1122
+ changeMsrpSession: changeMsrpSessionListener
1123
+ msrpSyncCompleted: msrpSyncCompletedListener
1124
+ msrpConversationCreated: msrpConversationCreatedListener
1125
+ msrpConversationRemoved: msrpConversationRemovedListener
1126
+ msrpConversationUpdated: msrpConversationUpdatedListener
1127
+ msrpMessageAdded: msrpMessageAddedListener
1128
+ msrpReceiptChanged: msrpReceiptChangedListener
1129
+ msrpReactionChanged: msrpReactionChangedListener
1130
+ msrpTyping: msrpTypingListener
884
1131
  // JANUS
885
1132
  conferenceStart: conferenceStartListener
886
1133
  conferenceEnd: conferenceEndListener