polfan-server-js-client 0.1.99922 → 0.1.99923
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/.gitmodules +3 -3
- package/.idea/deployment.xml +1 -8
- package/.idea/workspace.xml +142 -0
- package/build/index.js +149 -8
- package/build/index.js.map +1 -1
- package/build/types/AbstractChatClient.d.ts +114 -108
- package/build/types/AbstractRestClient.d.ts +21 -21
- package/build/types/AuthClient.d.ts +16 -16
- package/build/types/EventTarget.d.ts +18 -18
- package/build/types/FilesClient.d.ts +15 -15
- package/build/types/IndexedObjectCollection.d.ts +56 -56
- package/build/types/Permissions.d.ts +69 -69
- package/build/types/WebApiChatClient.d.ts +30 -30
- package/build/types/WebSocketChatClient.d.ts +38 -38
- package/build/types/index.d.ts +9 -9
- package/build/types/state-tracker/AsyncUtils.d.ts +15 -15
- package/build/types/state-tracker/ChatStateTracker.d.ts +31 -26
- package/build/types/state-tracker/EmoticonsManager.d.ts +15 -0
- package/build/types/state-tracker/MessagesManager.d.ts +55 -55
- package/build/types/state-tracker/PermissionsManager.d.ts +42 -42
- package/build/types/state-tracker/RoomMessagesHistory.d.ts +17 -17
- package/build/types/state-tracker/RoomsManager.d.ts +53 -53
- package/build/types/state-tracker/SpacesManager.d.ts +52 -52
- package/build/types/state-tracker/TopicHistoryWindow.d.ts +75 -75
- package/build/types/state-tracker/functions.d.ts +2 -2
- package/build/types/types/src/index.d.ts +102 -95
- package/build/types/types/src/schemes/ChatLocation.d.ts +5 -5
- package/build/types/types/src/schemes/Emoticon.d.ts +8 -0
- package/build/types/types/src/schemes/Envelope.d.ts +5 -5
- package/build/types/types/src/schemes/FollowedTopic.d.ts +6 -6
- package/build/types/types/src/schemes/Message.d.ts +13 -13
- package/build/types/types/src/schemes/PermissionOverwritesValue.d.ts +4 -4
- package/build/types/types/src/schemes/Role.d.ts +6 -6
- package/build/types/types/src/schemes/Room.d.ts +16 -16
- package/build/types/types/src/schemes/RoomMember.d.ts +7 -7
- package/build/types/types/src/schemes/RoomSummary.d.ts +5 -5
- package/build/types/types/src/schemes/Space.d.ts +13 -13
- package/build/types/types/src/schemes/SpaceMember.d.ts +5 -5
- package/build/types/types/src/schemes/SpaceSummary.d.ts +7 -7
- package/build/types/types/src/schemes/Topic.d.ts +8 -8
- package/build/types/types/src/schemes/User.d.ts +8 -8
- package/build/types/types/src/schemes/UserState.d.ts +6 -6
- package/build/types/types/src/schemes/commands/Ack.d.ts +5 -5
- package/build/types/types/src/schemes/commands/AssignRole.d.ts +6 -6
- package/build/types/types/src/schemes/commands/CreateEmoticon.d.ts +5 -0
- package/build/types/types/src/schemes/commands/CreateMessage.d.ts +6 -6
- package/build/types/types/src/schemes/commands/CreateOwner.d.ts +5 -5
- package/build/types/types/src/schemes/commands/CreateRole.d.ts +5 -5
- package/build/types/types/src/schemes/commands/CreateRoom.d.ts +8 -8
- package/build/types/types/src/schemes/commands/CreateSpace.d.ts +3 -3
- package/build/types/types/src/schemes/commands/CreateTopic.d.ts +8 -8
- package/build/types/types/src/schemes/commands/DeassignRole.d.ts +6 -6
- package/build/types/types/src/schemes/commands/DeleteEmoticon.d.ts +3 -0
- package/build/types/types/src/schemes/commands/DeleteOwner.d.ts +5 -5
- package/build/types/types/src/schemes/commands/DeleteRole.d.ts +4 -4
- package/build/types/types/src/schemes/commands/DeleteRoom.d.ts +3 -3
- package/build/types/types/src/schemes/commands/DeleteSpace.d.ts +3 -3
- package/build/types/types/src/schemes/commands/DeleteTopic.d.ts +4 -4
- package/build/types/types/src/schemes/commands/FollowTopic.d.ts +4 -4
- package/build/types/types/src/schemes/commands/GetComputedPermissions.d.ts +4 -4
- package/build/types/types/src/schemes/commands/GetDiscoverableSpaces.d.ts +2 -2
- package/build/types/types/src/schemes/commands/GetEmoticons.d.ts +3 -0
- package/build/types/types/src/schemes/commands/GetFollowedTopics.d.ts +4 -4
- package/build/types/types/src/schemes/commands/GetMessages.d.ts +6 -6
- package/build/types/types/src/schemes/commands/GetOwners.d.ts +4 -4
- package/build/types/types/src/schemes/commands/GetPermissionOverwriteTargets.d.ts +4 -4
- package/build/types/types/src/schemes/commands/GetPermissionOverwrites.d.ts +6 -6
- package/build/types/types/src/schemes/commands/GetRoomMembers.d.ts +3 -3
- package/build/types/types/src/schemes/commands/GetSession.d.ts +2 -2
- package/build/types/types/src/schemes/commands/GetSpaceMembers.d.ts +3 -3
- package/build/types/types/src/schemes/commands/GetSpaceRooms.d.ts +3 -3
- package/build/types/types/src/schemes/commands/GetTopics.d.ts +4 -4
- package/build/types/types/src/schemes/commands/JoinRoom.d.ts +3 -3
- package/build/types/types/src/schemes/commands/JoinSpace.d.ts +3 -3
- package/build/types/types/src/schemes/commands/LeaveRoom.d.ts +3 -3
- package/build/types/types/src/schemes/commands/LeaveSpace.d.ts +3 -3
- package/build/types/types/src/schemes/commands/SetPermissionOverwrites.d.ts +8 -8
- package/build/types/types/src/schemes/commands/UnfollowTopic.d.ts +4 -4
- package/build/types/types/src/schemes/commands/UpdateRole.d.ts +7 -7
- package/build/types/types/src/schemes/commands/UpdateRoom.d.ts +6 -6
- package/build/types/types/src/schemes/commands/UpdateSpace.d.ts +11 -9
- package/build/types/types/src/schemes/commands/UpdateTopic.d.ts +5 -5
- package/build/types/types/src/schemes/events/Bye.d.ts +3 -3
- package/build/types/types/src/schemes/events/ComputedPermissions.d.ts +5 -5
- package/build/types/types/src/schemes/events/DiscoverableSpaces.d.ts +4 -4
- package/build/types/types/src/schemes/events/EmoticonDeleted.d.ts +4 -0
- package/build/types/types/src/schemes/events/Emoticons.d.ts +6 -0
- package/build/types/types/src/schemes/events/Error.d.ts +4 -4
- package/build/types/types/src/schemes/events/FollowedTopicUpdated.d.ts +4 -4
- package/build/types/types/src/schemes/events/FollowedTopics.d.ts +6 -6
- package/build/types/types/src/schemes/events/Messages.d.ts +6 -6
- package/build/types/types/src/schemes/events/NewEmoticon.d.ts +4 -0
- package/build/types/types/src/schemes/events/NewMessage.d.ts +4 -4
- package/build/types/types/src/schemes/events/NewRole.d.ts +5 -5
- package/build/types/types/src/schemes/events/NewRoom.d.ts +5 -5
- package/build/types/types/src/schemes/events/NewTopic.d.ts +5 -5
- package/build/types/types/src/schemes/events/Ok.d.ts +2 -2
- package/build/types/types/src/schemes/events/Owners.d.ts +8 -8
- package/build/types/types/src/schemes/events/PermissionOverwriteTargets.d.ts +10 -10
- package/build/types/types/src/schemes/events/PermissionOverwrites.d.ts +8 -8
- package/build/types/types/src/schemes/events/PermissionOverwritesUpdated.d.ts +8 -8
- package/build/types/types/src/schemes/events/RoleDeleted.d.ts +4 -4
- package/build/types/types/src/schemes/events/RoleUpdated.d.ts +5 -5
- package/build/types/types/src/schemes/events/RoomDeleted.d.ts +3 -3
- package/build/types/types/src/schemes/events/RoomJoined.d.ts +4 -4
- package/build/types/types/src/schemes/events/RoomLeft.d.ts +3 -3
- package/build/types/types/src/schemes/events/RoomMemberJoined.d.ts +5 -5
- package/build/types/types/src/schemes/events/RoomMemberLeft.d.ts +4 -4
- package/build/types/types/src/schemes/events/RoomMemberUpdated.d.ts +6 -6
- package/build/types/types/src/schemes/events/RoomMembers.d.ts +5 -5
- package/build/types/types/src/schemes/events/RoomUpdated.d.ts +4 -4
- package/build/types/types/src/schemes/events/Session.d.ts +7 -7
- package/build/types/types/src/schemes/events/SpaceDeleted.d.ts +3 -3
- package/build/types/types/src/schemes/events/SpaceJoined.d.ts +4 -4
- package/build/types/types/src/schemes/events/SpaceLeft.d.ts +3 -3
- package/build/types/types/src/schemes/events/SpaceMemberJoined.d.ts +5 -5
- package/build/types/types/src/schemes/events/SpaceMemberLeft.d.ts +4 -4
- package/build/types/types/src/schemes/events/SpaceMemberUpdated.d.ts +6 -6
- package/build/types/types/src/schemes/events/SpaceMembers.d.ts +5 -5
- package/build/types/types/src/schemes/events/SpaceRooms.d.ts +5 -5
- package/build/types/types/src/schemes/events/SpaceUpdated.d.ts +4 -4
- package/build/types/types/src/schemes/events/TopicDeleted.d.ts +4 -4
- package/build/types/types/src/schemes/events/TopicFollowed.d.ts +4 -4
- package/build/types/types/src/schemes/events/TopicUnfollowed.d.ts +4 -4
- package/build/types/types/src/schemes/events/TopicUpdated.d.ts +6 -6
- package/build/types/types/src/schemes/events/Topics.d.ts +6 -6
- package/build/types/types/src/schemes/events/UserUpdated.d.ts +4 -4
- package/jest.config.ts +199 -199
- package/package.json +1 -1
- package/src/AbstractChatClient.ts +17 -2
- package/src/AuthClient.ts +45 -45
- package/src/EventTarget.ts +48 -48
- package/src/IndexedObjectCollection.ts +225 -225
- package/src/WebApiChatClient.ts +94 -94
- package/src/WebSocketChatClient.ts +131 -131
- package/src/index.ts +22 -22
- package/src/state-tracker/ChatStateTracker.ts +46 -41
- package/src/state-tracker/EmoticonsManager.ts +67 -0
- package/src/state-tracker/RoomMessagesHistory.ts +73 -73
- package/src/types/src/index.ts +14 -0
- package/src/types/src/schemes/Emoticon.ts +9 -0
- package/src/types/src/schemes/commands/CreateEmoticon.ts +5 -0
- package/src/types/src/schemes/commands/DeleteEmoticon.ts +3 -0
- package/src/types/src/schemes/commands/GetEmoticons.ts +3 -0
- package/src/types/src/schemes/commands/UpdateSpace.ts +3 -0
- package/src/types/src/schemes/events/EmoticonDeleted.ts +4 -0
- package/src/types/src/schemes/events/Emoticons.ts +7 -0
- package/src/types/src/schemes/events/NewEmoticon.ts +5 -0
- package/.idea/inspectionProfiles/Project_Default.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/php.xml +0 -18
- package/.idea/polfan-server-js-client.iml +0 -10
|
@@ -1,132 +1,132 @@
|
|
|
1
|
-
import {ObservableInterface} from "./EventTarget";
|
|
2
|
-
import {AbstractChatClient, CommandResult, CommandsMap} from "./AbstractChatClient";
|
|
3
|
-
import {ChatStateTracker} from "./state-tracker/ChatStateTracker";
|
|
4
|
-
import {Envelope} from "./types/src";
|
|
5
|
-
|
|
6
|
-
export interface WebSocketClientOptions {
|
|
7
|
-
url: string;
|
|
8
|
-
token?: string;
|
|
9
|
-
temporaryNick?: string;
|
|
10
|
-
connectingTimeoutMs?: number;
|
|
11
|
-
awaitQueueSendDelayMs?: number;
|
|
12
|
-
stateTracking?: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
enum WebSocketChatClientEvent {
|
|
16
|
-
connect = 'connect',
|
|
17
|
-
disconnect = 'disconnect',
|
|
18
|
-
message = 'message',
|
|
19
|
-
error = 'error',
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class WebSocketChatClient extends AbstractChatClient implements ObservableInterface {
|
|
23
|
-
public readonly Event = WebSocketChatClientEvent;
|
|
24
|
-
public readonly state?: ChatStateTracker;
|
|
25
|
-
|
|
26
|
-
protected ws: WebSocket|null = null;
|
|
27
|
-
protected sendQueue: Envelope[] = [];
|
|
28
|
-
protected connectingTimeoutId: any;
|
|
29
|
-
protected authenticated: boolean;
|
|
30
|
-
protected authenticatedResolvers: [() => void, (error: Error) => void];
|
|
31
|
-
|
|
32
|
-
public constructor(private readonly options: WebSocketClientOptions) {
|
|
33
|
-
super();
|
|
34
|
-
if (!this.options.token && !this.options.temporaryNick) {
|
|
35
|
-
throw new Error('Token or temporary nick is required');
|
|
36
|
-
}
|
|
37
|
-
if (this.options.stateTracking ?? true) {
|
|
38
|
-
this.state = new ChatStateTracker(this);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
public async connect(): Promise<void> {
|
|
43
|
-
const authString = this.options.token ? `token=${this.options.token}` : `nick=${this.options.temporaryNick}`;
|
|
44
|
-
this.ws = new WebSocket(`${this.options.url}?${authString}`);
|
|
45
|
-
this.ws.onclose = ev => this.onClose(ev);
|
|
46
|
-
this.ws.onmessage = ev => this.onMessage(ev);
|
|
47
|
-
this.connectingTimeoutId = setTimeout(
|
|
48
|
-
() => this.triggerConnectionTimeout(),
|
|
49
|
-
this.options.connectingTimeoutMs ?? 10000
|
|
50
|
-
);
|
|
51
|
-
this.authenticated = false;
|
|
52
|
-
return new Promise((...args) => this.authenticatedResolvers = args);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
public disconnect(): void {
|
|
56
|
-
this.sendQueue = [];
|
|
57
|
-
this.ws?.close();
|
|
58
|
-
this.ws = null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public async send<CommandType extends keyof CommandsMap>(commandType: CommandType, commandData: CommandsMap[CommandType][0]):
|
|
62
|
-
Promise<CommandResult<CommandsMap[CommandType][1]>> {
|
|
63
|
-
if (!this.ws || [this.ws.CLOSED, this.ws.CLOSING].includes(this.ws.readyState)) {
|
|
64
|
-
throw new Error('Cannot send; close or closing connection state');
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const envelope = this.createEnvelope<CommandsMap[CommandType][0]>(commandType, commandData);
|
|
68
|
-
const promise = this.createPromiseFromCommandEnvelope<CommandType>(envelope);
|
|
69
|
-
|
|
70
|
-
if (this.ws.readyState === this.ws.CONNECTING || !this.authenticated) {
|
|
71
|
-
this.sendQueue.push(envelope);
|
|
72
|
-
return promise;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (this.ws.readyState !== this.ws.OPEN) {
|
|
76
|
-
throw new Error(`Invalid websocket state=${this.ws.readyState}`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
this.sendEnvelope(envelope);
|
|
80
|
-
return promise;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private sendEnvelope(envelope: Envelope): void {
|
|
84
|
-
this.ws.send(JSON.stringify(envelope));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
private onMessage(event: MessageEvent): void {
|
|
88
|
-
const envelope: Envelope = JSON.parse(event.data);
|
|
89
|
-
this.handleIncomingEnvelope(envelope);
|
|
90
|
-
this.emit(envelope.type, envelope.data);
|
|
91
|
-
this.emit(this.Event.message, envelope);
|
|
92
|
-
|
|
93
|
-
// Login successfully
|
|
94
|
-
if (!this.authenticated) {
|
|
95
|
-
const isAuthenticated = envelope.type !== 'Error';
|
|
96
|
-
this.authenticated = isAuthenticated;
|
|
97
|
-
if (isAuthenticated) {
|
|
98
|
-
this.authenticatedResolvers[0]();
|
|
99
|
-
this.emit(this.Event.connect);
|
|
100
|
-
this.sendFromQueue();
|
|
101
|
-
} else {
|
|
102
|
-
this.authenticatedResolvers[1](envelope.data);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
private onClose(event: CloseEvent): void {
|
|
108
|
-
clearTimeout(this.connectingTimeoutId);
|
|
109
|
-
const reconnect = event.code !== 1000; // Connection was closed because of error
|
|
110
|
-
if (reconnect) {
|
|
111
|
-
this.connect();
|
|
112
|
-
}
|
|
113
|
-
this.emit(this.Event.disconnect, reconnect);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
private sendFromQueue(): void {
|
|
117
|
-
// Send awaiting data to server
|
|
118
|
-
let lastDelay = 0;
|
|
119
|
-
for (const dataIndex in this.sendQueue) {
|
|
120
|
-
const envelope = this.sendQueue[dataIndex];
|
|
121
|
-
setTimeout(() => this.sendEnvelope(envelope), lastDelay);
|
|
122
|
-
lastDelay += this.options.awaitQueueSendDelayMs ?? 500;
|
|
123
|
-
}
|
|
124
|
-
this.sendQueue = [];
|
|
125
|
-
clearTimeout(this.connectingTimeoutId);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private triggerConnectionTimeout(): void {
|
|
129
|
-
this.disconnect();
|
|
130
|
-
this.emit(this.Event.error, new Error('Connection timeout'));
|
|
131
|
-
}
|
|
1
|
+
import {ObservableInterface} from "./EventTarget";
|
|
2
|
+
import {AbstractChatClient, CommandResult, CommandsMap} from "./AbstractChatClient";
|
|
3
|
+
import {ChatStateTracker} from "./state-tracker/ChatStateTracker";
|
|
4
|
+
import {Envelope} from "./types/src";
|
|
5
|
+
|
|
6
|
+
export interface WebSocketClientOptions {
|
|
7
|
+
url: string;
|
|
8
|
+
token?: string;
|
|
9
|
+
temporaryNick?: string;
|
|
10
|
+
connectingTimeoutMs?: number;
|
|
11
|
+
awaitQueueSendDelayMs?: number;
|
|
12
|
+
stateTracking?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
enum WebSocketChatClientEvent {
|
|
16
|
+
connect = 'connect',
|
|
17
|
+
disconnect = 'disconnect',
|
|
18
|
+
message = 'message',
|
|
19
|
+
error = 'error',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class WebSocketChatClient extends AbstractChatClient implements ObservableInterface {
|
|
23
|
+
public readonly Event = WebSocketChatClientEvent;
|
|
24
|
+
public readonly state?: ChatStateTracker;
|
|
25
|
+
|
|
26
|
+
protected ws: WebSocket|null = null;
|
|
27
|
+
protected sendQueue: Envelope[] = [];
|
|
28
|
+
protected connectingTimeoutId: any;
|
|
29
|
+
protected authenticated: boolean;
|
|
30
|
+
protected authenticatedResolvers: [() => void, (error: Error) => void];
|
|
31
|
+
|
|
32
|
+
public constructor(private readonly options: WebSocketClientOptions) {
|
|
33
|
+
super();
|
|
34
|
+
if (!this.options.token && !this.options.temporaryNick) {
|
|
35
|
+
throw new Error('Token or temporary nick is required');
|
|
36
|
+
}
|
|
37
|
+
if (this.options.stateTracking ?? true) {
|
|
38
|
+
this.state = new ChatStateTracker(this);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public async connect(): Promise<void> {
|
|
43
|
+
const authString = this.options.token ? `token=${this.options.token}` : `nick=${this.options.temporaryNick}`;
|
|
44
|
+
this.ws = new WebSocket(`${this.options.url}?${authString}`);
|
|
45
|
+
this.ws.onclose = ev => this.onClose(ev);
|
|
46
|
+
this.ws.onmessage = ev => this.onMessage(ev);
|
|
47
|
+
this.connectingTimeoutId = setTimeout(
|
|
48
|
+
() => this.triggerConnectionTimeout(),
|
|
49
|
+
this.options.connectingTimeoutMs ?? 10000
|
|
50
|
+
);
|
|
51
|
+
this.authenticated = false;
|
|
52
|
+
return new Promise((...args) => this.authenticatedResolvers = args);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public disconnect(): void {
|
|
56
|
+
this.sendQueue = [];
|
|
57
|
+
this.ws?.close();
|
|
58
|
+
this.ws = null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public async send<CommandType extends keyof CommandsMap>(commandType: CommandType, commandData: CommandsMap[CommandType][0]):
|
|
62
|
+
Promise<CommandResult<CommandsMap[CommandType][1]>> {
|
|
63
|
+
if (!this.ws || [this.ws.CLOSED, this.ws.CLOSING].includes(this.ws.readyState)) {
|
|
64
|
+
throw new Error('Cannot send; close or closing connection state');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const envelope = this.createEnvelope<CommandsMap[CommandType][0]>(commandType, commandData);
|
|
68
|
+
const promise = this.createPromiseFromCommandEnvelope<CommandType>(envelope);
|
|
69
|
+
|
|
70
|
+
if (this.ws.readyState === this.ws.CONNECTING || !this.authenticated) {
|
|
71
|
+
this.sendQueue.push(envelope);
|
|
72
|
+
return promise;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (this.ws.readyState !== this.ws.OPEN) {
|
|
76
|
+
throw new Error(`Invalid websocket state=${this.ws.readyState}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this.sendEnvelope(envelope);
|
|
80
|
+
return promise;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private sendEnvelope(envelope: Envelope): void {
|
|
84
|
+
this.ws.send(JSON.stringify(envelope));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private onMessage(event: MessageEvent): void {
|
|
88
|
+
const envelope: Envelope = JSON.parse(event.data);
|
|
89
|
+
this.handleIncomingEnvelope(envelope);
|
|
90
|
+
this.emit(envelope.type, envelope.data);
|
|
91
|
+
this.emit(this.Event.message, envelope);
|
|
92
|
+
|
|
93
|
+
// Login successfully
|
|
94
|
+
if (!this.authenticated) {
|
|
95
|
+
const isAuthenticated = envelope.type !== 'Error';
|
|
96
|
+
this.authenticated = isAuthenticated;
|
|
97
|
+
if (isAuthenticated) {
|
|
98
|
+
this.authenticatedResolvers[0]();
|
|
99
|
+
this.emit(this.Event.connect);
|
|
100
|
+
this.sendFromQueue();
|
|
101
|
+
} else {
|
|
102
|
+
this.authenticatedResolvers[1](envelope.data);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private onClose(event: CloseEvent): void {
|
|
108
|
+
clearTimeout(this.connectingTimeoutId);
|
|
109
|
+
const reconnect = event.code !== 1000; // Connection was closed because of error
|
|
110
|
+
if (reconnect) {
|
|
111
|
+
this.connect();
|
|
112
|
+
}
|
|
113
|
+
this.emit(this.Event.disconnect, reconnect);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private sendFromQueue(): void {
|
|
117
|
+
// Send awaiting data to server
|
|
118
|
+
let lastDelay = 0;
|
|
119
|
+
for (const dataIndex in this.sendQueue) {
|
|
120
|
+
const envelope = this.sendQueue[dataIndex];
|
|
121
|
+
setTimeout(() => this.sendEnvelope(envelope), lastDelay);
|
|
122
|
+
lastDelay += this.options.awaitQueueSendDelayMs ?? 500;
|
|
123
|
+
}
|
|
124
|
+
this.sendQueue = [];
|
|
125
|
+
clearTimeout(this.connectingTimeoutId);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private triggerConnectionTimeout(): void {
|
|
129
|
+
this.disconnect();
|
|
130
|
+
this.emit(this.Event.error, new Error('Connection timeout'));
|
|
131
|
+
}
|
|
132
132
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import {WebSocketChatClient} from "./WebSocketChatClient";
|
|
2
|
-
import {WebApiChatClient} from "./WebApiChatClient";
|
|
3
|
-
import {
|
|
4
|
-
IndexedCollection,
|
|
5
|
-
IndexedObjectCollection,
|
|
6
|
-
ObservableIndexedCollection,
|
|
7
|
-
ObservableIndexedObjectCollection
|
|
8
|
-
} from "./IndexedObjectCollection";
|
|
9
|
-
import { AuthClient, MyAccountInterface, TokenInterface } from "./AuthClient";
|
|
10
|
-
import {FilesClient, File} from "./FilesClient";
|
|
11
|
-
import { Permissions, PermissionDefinition, Layer } from "./Permissions";
|
|
12
|
-
import * as ChatTypes from './types/src';
|
|
13
|
-
|
|
14
|
-
export {
|
|
15
|
-
IndexedCollection, ObservableIndexedCollection,
|
|
16
|
-
IndexedObjectCollection, ObservableIndexedObjectCollection,
|
|
17
|
-
Permissions, PermissionDefinition, Layer,
|
|
18
|
-
WebSocketChatClient, WebApiChatClient,
|
|
19
|
-
AuthClient, MyAccountInterface, TokenInterface,
|
|
20
|
-
FilesClient, File
|
|
21
|
-
};
|
|
22
|
-
|
|
1
|
+
import {WebSocketChatClient} from "./WebSocketChatClient";
|
|
2
|
+
import {WebApiChatClient} from "./WebApiChatClient";
|
|
3
|
+
import {
|
|
4
|
+
IndexedCollection,
|
|
5
|
+
IndexedObjectCollection,
|
|
6
|
+
ObservableIndexedCollection,
|
|
7
|
+
ObservableIndexedObjectCollection
|
|
8
|
+
} from "./IndexedObjectCollection";
|
|
9
|
+
import { AuthClient, MyAccountInterface, TokenInterface } from "./AuthClient";
|
|
10
|
+
import {FilesClient, File} from "./FilesClient";
|
|
11
|
+
import { Permissions, PermissionDefinition, Layer } from "./Permissions";
|
|
12
|
+
import * as ChatTypes from './types/src';
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
IndexedCollection, ObservableIndexedCollection,
|
|
16
|
+
IndexedObjectCollection, ObservableIndexedObjectCollection,
|
|
17
|
+
Permissions, PermissionDefinition, Layer,
|
|
18
|
+
WebSocketChatClient, WebApiChatClient,
|
|
19
|
+
AuthClient, MyAccountInterface, TokenInterface,
|
|
20
|
+
FilesClient, File
|
|
21
|
+
};
|
|
22
|
+
|
|
23
23
|
export type {ChatTypes};
|
|
@@ -1,42 +1,47 @@
|
|
|
1
|
-
import {WebSocketChatClient} from "../WebSocketChatClient";
|
|
2
|
-
import {Session, User} from "../types/src";
|
|
3
|
-
import {RoomsManager} from "./RoomsManager";
|
|
4
|
-
import {SpacesManager} from "./SpacesManager";
|
|
5
|
-
import {PermissionsManager} from "./PermissionsManager";
|
|
6
|
-
import {DeferredTask} from "./AsyncUtils";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
public
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return this._me;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
this.
|
|
40
|
-
this.
|
|
41
|
-
}
|
|
1
|
+
import {WebSocketChatClient} from "../WebSocketChatClient";
|
|
2
|
+
import {Session, User} from "../types/src";
|
|
3
|
+
import {RoomsManager} from "./RoomsManager";
|
|
4
|
+
import {SpacesManager} from "./SpacesManager";
|
|
5
|
+
import {PermissionsManager} from "./PermissionsManager";
|
|
6
|
+
import {DeferredTask} from "./AsyncUtils";
|
|
7
|
+
import {EmoticonsManager} from "./EmoticonsManager";
|
|
8
|
+
|
|
9
|
+
export class ChatStateTracker {
|
|
10
|
+
/**
|
|
11
|
+
* State of your permissions.
|
|
12
|
+
*/
|
|
13
|
+
public readonly permissions = new PermissionsManager(this);
|
|
14
|
+
/**
|
|
15
|
+
* State of the rooms you are in.
|
|
16
|
+
*/
|
|
17
|
+
public readonly rooms: RoomsManager = new RoomsManager(this);
|
|
18
|
+
/**
|
|
19
|
+
* State of the spaces you are in.
|
|
20
|
+
*/
|
|
21
|
+
public readonly spaces = new SpacesManager(this);
|
|
22
|
+
/**
|
|
23
|
+
* State of the emoticons (global and space-related).
|
|
24
|
+
*/
|
|
25
|
+
public readonly emoticons = new EmoticonsManager(this);
|
|
26
|
+
|
|
27
|
+
private _me: User = null;
|
|
28
|
+
private readonly deferredSession = new DeferredTask();
|
|
29
|
+
|
|
30
|
+
public constructor(public readonly client: WebSocketChatClient) {
|
|
31
|
+
this.client.on('Session', ev => this.handleSession(ev));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public get me(): User | null {
|
|
35
|
+
return this._me;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public async getMe(): Promise<User> {
|
|
39
|
+
await this.deferredSession.promise;
|
|
40
|
+
return this._me;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private handleSession(ev: Session): void {
|
|
44
|
+
this._me = ev.user;
|
|
45
|
+
this.deferredSession.resolve();
|
|
46
|
+
}
|
|
42
47
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {ChatStateTracker} from "./ChatStateTracker";
|
|
2
|
+
import {
|
|
3
|
+
IndexedCollection,
|
|
4
|
+
ObservableIndexedObjectCollection
|
|
5
|
+
} from "../IndexedObjectCollection";
|
|
6
|
+
import {Emoticon, EmoticonDeleted, Emoticons, NewEmoticon, SpaceDeleted} from "../types/src";
|
|
7
|
+
import {PromiseRegistry} from "./AsyncUtils";
|
|
8
|
+
|
|
9
|
+
const GLOBAL_KEY = 'global';
|
|
10
|
+
|
|
11
|
+
export class EmoticonsManager {
|
|
12
|
+
private list: IndexedCollection<string, ObservableIndexedObjectCollection<Emoticon>> = new IndexedCollection();
|
|
13
|
+
private emoticonsPromises = new PromiseRegistry();
|
|
14
|
+
|
|
15
|
+
public constructor(private tracker: ChatStateTracker) {
|
|
16
|
+
this.tracker.client.on('Emoticons', ev => this.handleEmoticons(ev));
|
|
17
|
+
this.tracker.client.on('NewEmoticon', ev => this.handleNewEmoticon(ev));
|
|
18
|
+
this.tracker.client.on('EmoticonDeleted', ev => this.handleEmoticonDeleted(ev));
|
|
19
|
+
this.tracker.client.on('SpaceDeleted', ev => this.handleSpaceDeleted(ev));
|
|
20
|
+
this.tracker.client.on('Session', () => this.handleSession());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public async get(spaceId?: string): Promise<ObservableIndexedObjectCollection<Emoticon>> {
|
|
24
|
+
if (this.emoticonsPromises.notExist(spaceId)) {
|
|
25
|
+
this.emoticonsPromises.registerByFunction(async () => {
|
|
26
|
+
const result = await this.tracker.client.send('GetEmoticons', {spaceId});
|
|
27
|
+
if (result.error) {
|
|
28
|
+
throw result.error;
|
|
29
|
+
}
|
|
30
|
+
this.handleEmoticons(result.data);
|
|
31
|
+
}, spaceId ?? GLOBAL_KEY);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await this.emoticonsPromises.get(spaceId);
|
|
35
|
+
return this.list.get(spaceId);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private handleEmoticons(event: Emoticons): void {
|
|
39
|
+
const spaceId = event.location.spaceId ?? GLOBAL_KEY;
|
|
40
|
+
|
|
41
|
+
if (!this.list.has(spaceId)) {
|
|
42
|
+
this.list.set([spaceId, new ObservableIndexedObjectCollection<Emoticon>('id')]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const collection = this.list.get(spaceId);
|
|
46
|
+
collection.set(...event.emoticons);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private handleNewEmoticon(ev: NewEmoticon): void {
|
|
50
|
+
const collection = this.list.get(ev.emoticon.spaceId ?? GLOBAL_KEY);
|
|
51
|
+
collection?.set(ev.emoticon);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private handleEmoticonDeleted(ev: EmoticonDeleted): void {
|
|
55
|
+
const collection = this.list.get(ev.spaceId ?? GLOBAL_KEY);
|
|
56
|
+
collection?.delete(ev.emoticonId);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private handleSpaceDeleted(event: SpaceDeleted): void {
|
|
60
|
+
this.list.delete(event.id);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private handleSession(): void {
|
|
64
|
+
this.list.deleteAll();
|
|
65
|
+
this.emoticonsPromises.forgetAll();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
import {ChatStateTracker} from "./ChatStateTracker";
|
|
2
|
-
import {NewTopic, Room, RoomUpdated, Topic, TopicDeleted} from "../types/src";
|
|
3
|
-
import {IndexedCollection,} from "../IndexedObjectCollection";
|
|
4
|
-
import {TopicHistoryWindow} from "./TopicHistoryWindow";
|
|
5
|
-
|
|
6
|
-
export class RoomMessagesHistory {
|
|
7
|
-
private historyWindows = new IndexedCollection<string, TopicHistoryWindow>();
|
|
8
|
-
|
|
9
|
-
public constructor(
|
|
10
|
-
private room: Room,
|
|
11
|
-
private tracker: ChatStateTracker,
|
|
12
|
-
) {
|
|
13
|
-
this.tracker.client.on('RoomUpdated', ev => this.handleRoomUpdated(ev));
|
|
14
|
-
this.tracker.client.on('NewTopic', ev => this.handleNewTopic(ev));
|
|
15
|
-
this.tracker.client.on('TopicDeleted', ev => this.handleTopicDeleted(ev));
|
|
16
|
-
|
|
17
|
-
if (this.room.defaultTopic) {
|
|
18
|
-
this.createHistoryWindowForTopic(this.room.defaultTopic);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Returns a history window object for the given topic ID, allowing you to view message history.
|
|
24
|
-
*/
|
|
25
|
-
public async getMessagesWindow(topicId: string): Promise<TopicHistoryWindow | undefined> {
|
|
26
|
-
let historyWindow = this.historyWindows.get(topicId);
|
|
27
|
-
|
|
28
|
-
if (! historyWindow) {
|
|
29
|
-
const topic = (await this.tracker.rooms.getTopics(this.room.id, [topicId])).get(topicId);
|
|
30
|
-
|
|
31
|
-
if (topic) {
|
|
32
|
-
this.createHistoryWindowForTopic(topic);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return this.historyWindows.get(topicId);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
private handleRoomUpdated(ev: RoomUpdated): void {
|
|
40
|
-
if (this.room.id === ev.room.id) {
|
|
41
|
-
this.room = ev.room;
|
|
42
|
-
|
|
43
|
-
if (ev.room.defaultTopic) {
|
|
44
|
-
this.createHistoryWindowForTopic(ev.room.defaultTopic);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
private handleNewTopic(ev: NewTopic): void {
|
|
50
|
-
if (this.room.id === ev.roomId) {
|
|
51
|
-
this.createHistoryWindowForTopic(ev.topic);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private handleTopicDeleted(ev: TopicDeleted): void {
|
|
56
|
-
if (this.room.id === ev.location.roomId) {
|
|
57
|
-
this.historyWindows.delete(ev.location.topicId);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
private createHistoryWindowForTopic(topic: Topic): void {
|
|
62
|
-
if (this.historyWindows.has(topic.id)) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
this.historyWindows.set([topic.id, new TopicHistoryWindow(this.room.id, topic.id, this.tracker)]);
|
|
67
|
-
|
|
68
|
-
// If new topic refers to some message from this room, update other structures
|
|
69
|
-
if (topic.refMessage) {
|
|
70
|
-
const refHistoryWindow = this.historyWindows.get(topic.refMessage.location.topicId);
|
|
71
|
-
refHistoryWindow?._updateMessageReference(topic);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
1
|
+
import {ChatStateTracker} from "./ChatStateTracker";
|
|
2
|
+
import {NewTopic, Room, RoomUpdated, Topic, TopicDeleted} from "../types/src";
|
|
3
|
+
import {IndexedCollection,} from "../IndexedObjectCollection";
|
|
4
|
+
import {TopicHistoryWindow} from "./TopicHistoryWindow";
|
|
5
|
+
|
|
6
|
+
export class RoomMessagesHistory {
|
|
7
|
+
private historyWindows = new IndexedCollection<string, TopicHistoryWindow>();
|
|
8
|
+
|
|
9
|
+
public constructor(
|
|
10
|
+
private room: Room,
|
|
11
|
+
private tracker: ChatStateTracker,
|
|
12
|
+
) {
|
|
13
|
+
this.tracker.client.on('RoomUpdated', ev => this.handleRoomUpdated(ev));
|
|
14
|
+
this.tracker.client.on('NewTopic', ev => this.handleNewTopic(ev));
|
|
15
|
+
this.tracker.client.on('TopicDeleted', ev => this.handleTopicDeleted(ev));
|
|
16
|
+
|
|
17
|
+
if (this.room.defaultTopic) {
|
|
18
|
+
this.createHistoryWindowForTopic(this.room.defaultTopic);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Returns a history window object for the given topic ID, allowing you to view message history.
|
|
24
|
+
*/
|
|
25
|
+
public async getMessagesWindow(topicId: string): Promise<TopicHistoryWindow | undefined> {
|
|
26
|
+
let historyWindow = this.historyWindows.get(topicId);
|
|
27
|
+
|
|
28
|
+
if (! historyWindow) {
|
|
29
|
+
const topic = (await this.tracker.rooms.getTopics(this.room.id, [topicId])).get(topicId);
|
|
30
|
+
|
|
31
|
+
if (topic) {
|
|
32
|
+
this.createHistoryWindowForTopic(topic);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return this.historyWindows.get(topicId);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private handleRoomUpdated(ev: RoomUpdated): void {
|
|
40
|
+
if (this.room.id === ev.room.id) {
|
|
41
|
+
this.room = ev.room;
|
|
42
|
+
|
|
43
|
+
if (ev.room.defaultTopic) {
|
|
44
|
+
this.createHistoryWindowForTopic(ev.room.defaultTopic);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private handleNewTopic(ev: NewTopic): void {
|
|
50
|
+
if (this.room.id === ev.roomId) {
|
|
51
|
+
this.createHistoryWindowForTopic(ev.topic);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private handleTopicDeleted(ev: TopicDeleted): void {
|
|
56
|
+
if (this.room.id === ev.location.roomId) {
|
|
57
|
+
this.historyWindows.delete(ev.location.topicId);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private createHistoryWindowForTopic(topic: Topic): void {
|
|
62
|
+
if (this.historyWindows.has(topic.id)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.historyWindows.set([topic.id, new TopicHistoryWindow(this.room.id, topic.id, this.tracker)]);
|
|
67
|
+
|
|
68
|
+
// If new topic refers to some message from this room, update other structures
|
|
69
|
+
if (topic.refMessage) {
|
|
70
|
+
const refHistoryWindow = this.historyWindows.get(topic.refMessage.location.topicId);
|
|
71
|
+
refHistoryWindow?._updateMessageReference(topic);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
74
|
}
|
package/src/types/src/index.ts
CHANGED
|
@@ -92,6 +92,13 @@ import {TopicUpdated} from "./schemes/events/TopicUpdated";
|
|
|
92
92
|
import {GetDiscoverableSpaces} from "./schemes/commands/GetDiscoverableSpaces";
|
|
93
93
|
import {DiscoverableSpaces} from "./schemes/events/DiscoverableSpaces";
|
|
94
94
|
import {SpaceSummary} from "./schemes/SpaceSummary";
|
|
95
|
+
import {Emoticon} from "./schemes/Emoticon";
|
|
96
|
+
import {Emoticons} from "./schemes/events/Emoticons";
|
|
97
|
+
import {GetEmoticons} from "./schemes/commands/GetEmoticons";
|
|
98
|
+
import {CreateEmoticon} from "./schemes/commands/CreateEmoticon";
|
|
99
|
+
import {DeleteEmoticon} from "./schemes/commands/DeleteEmoticon";
|
|
100
|
+
import {NewEmoticon} from "./schemes/events/NewEmoticon";
|
|
101
|
+
import {EmoticonDeleted} from "./schemes/events/EmoticonDeleted";
|
|
95
102
|
|
|
96
103
|
export {
|
|
97
104
|
// objects
|
|
@@ -114,6 +121,7 @@ export {
|
|
|
114
121
|
ChatLocation,
|
|
115
122
|
SpaceSummary,
|
|
116
123
|
SpaceDiscoverable,
|
|
124
|
+
Emoticon,
|
|
117
125
|
// events
|
|
118
126
|
Bye,
|
|
119
127
|
Error,
|
|
@@ -156,6 +164,9 @@ export {
|
|
|
156
164
|
Owners,
|
|
157
165
|
Ok,
|
|
158
166
|
DiscoverableSpaces,
|
|
167
|
+
Emoticons,
|
|
168
|
+
EmoticonDeleted,
|
|
169
|
+
NewEmoticon,
|
|
159
170
|
// commands
|
|
160
171
|
AssignRole,
|
|
161
172
|
GetMessages,
|
|
@@ -195,4 +206,7 @@ export {
|
|
|
195
206
|
Topics,
|
|
196
207
|
GetTopics,
|
|
197
208
|
GetDiscoverableSpaces,
|
|
209
|
+
GetEmoticons,
|
|
210
|
+
CreateEmoticon,
|
|
211
|
+
DeleteEmoticon,
|
|
198
212
|
};
|