polfan-server-js-client 0.1.36 → 0.1.38
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/build/index.js +396 -217
- package/build/index.js.map +1 -1
- package/build/types/state-tracker/AsyncUtils.d.ts +14 -0
- package/build/types/state-tracker/PermissionsManager.d.ts +9 -0
- package/build/types/state-tracker/RoomsManager.d.ts +6 -10
- package/build/types/state-tracker/SpacesManager.d.ts +2 -1
- package/package.json +1 -1
- package/src/state-tracker/AsyncUtils.ts +38 -0
- package/src/state-tracker/ChatStateTracker.ts +1 -1
- package/src/state-tracker/PermissionsManager.ts +61 -14
- package/src/state-tracker/RoomsManager.ts +33 -23
- package/src/state-tracker/SpacesManager.ts +25 -26
- package/tests/async-utils.test.ts +30 -0
- package/build/types/state-tracker/DeferredTask.d.ts +0 -5
- package/src/state-tracker/DeferredTask.ts +0 -8
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare class DeferredTask {
|
|
2
|
+
readonly promise: Promise<void>;
|
|
3
|
+
resolve: () => void;
|
|
4
|
+
constructor();
|
|
5
|
+
}
|
|
6
|
+
export declare class PromiseRegistry {
|
|
7
|
+
private promises;
|
|
8
|
+
register<T = any>(promise: Promise<T>, key: string): void;
|
|
9
|
+
registerByFunction(fn: () => Promise<any>, key: string): void;
|
|
10
|
+
get<T = any>(key: string): Promise<T> | undefined;
|
|
11
|
+
has(key: string): boolean;
|
|
12
|
+
notExist(key: string): boolean;
|
|
13
|
+
forget(...keys: string[]): void;
|
|
14
|
+
}
|
|
@@ -5,6 +5,7 @@ import { Permission } from "../Permission";
|
|
|
5
5
|
export declare class PermissionsManager extends EventTarget {
|
|
6
6
|
private tracker;
|
|
7
7
|
private readonly overwrites;
|
|
8
|
+
private readonly overwritesPromises;
|
|
8
9
|
constructor(tracker: ChatStateTracker);
|
|
9
10
|
getOverwrites(layer: PermissionOverwrites['layer'], layerId: PermissionOverwrites['layerId'], target: PermissionOverwrites['target'], targetId: PermissionOverwrites['targetId']): Promise<PermissionOverwrites | undefined>;
|
|
10
11
|
on(eventName: 'change', handler: EventHandler<any>): this;
|
|
@@ -14,6 +15,14 @@ export declare class PermissionsManager extends EventTarget {
|
|
|
14
15
|
}>;
|
|
15
16
|
calculatePermissions(spaceId?: string, roomId?: string, topicId?: string): Promise<number>;
|
|
16
17
|
private handlePermissionOverwrites;
|
|
18
|
+
private handleSpaceDeleted;
|
|
19
|
+
private handleRoomDeleted;
|
|
20
|
+
private handleTopicDeleted;
|
|
21
|
+
private handleRoleDeleted;
|
|
22
|
+
/**
|
|
23
|
+
* @return Matched and deleted ids
|
|
24
|
+
*/
|
|
25
|
+
private deleteOverwritesByIdPrefix;
|
|
17
26
|
private collectRoleOverwrites;
|
|
18
27
|
private resolveOverwritesFromRolesByOrder;
|
|
19
28
|
private resolveOverwritesHierarchy;
|
|
@@ -9,6 +9,7 @@ export declare class RoomsManager {
|
|
|
9
9
|
private readonly topics;
|
|
10
10
|
private readonly members;
|
|
11
11
|
private readonly deferredSession;
|
|
12
|
+
private readonly membersPromises;
|
|
12
13
|
constructor(tracker: ChatStateTracker);
|
|
13
14
|
/**
|
|
14
15
|
* Get collection of room members.
|
|
@@ -26,22 +27,17 @@ export declare class RoomsManager {
|
|
|
26
27
|
* Get collection of room topics.
|
|
27
28
|
*/
|
|
28
29
|
getTopics(roomId: string): Promise<ObservableIndexedObjectCollection<Topic> | undefined>;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* @internal
|
|
32
|
-
*/
|
|
33
|
-
_delete(...roomIds: string[]): void;
|
|
34
|
-
/**
|
|
35
|
-
* For internal use. If you want to leave the room, execute a proper command on client object.
|
|
36
|
-
* @internal
|
|
37
|
-
*/
|
|
38
|
-
_deleteBySpaceId(spaceId: string): void;
|
|
30
|
+
private deleteRoom;
|
|
31
|
+
private deleteRoomsBySpaceId;
|
|
39
32
|
private handleSpaceMemberUpdated;
|
|
33
|
+
private handleSpaceMemberLeft;
|
|
40
34
|
private handleRoomMemberUpdated;
|
|
35
|
+
private handleSpaceDeleted;
|
|
41
36
|
private handleTopicDeleted;
|
|
42
37
|
private handleNewTopic;
|
|
43
38
|
private addJoinedRoomTopics;
|
|
44
39
|
private handleRoomJoined;
|
|
40
|
+
private handleRoomDeleted;
|
|
45
41
|
private addJoinedRooms;
|
|
46
42
|
private handleRoomLeft;
|
|
47
43
|
private handleRoomMemberJoined;
|
|
@@ -8,6 +8,8 @@ export declare class SpacesManager {
|
|
|
8
8
|
private readonly rooms;
|
|
9
9
|
private readonly members;
|
|
10
10
|
private readonly deferredSession;
|
|
11
|
+
private readonly roomsPromises;
|
|
12
|
+
private readonly membersPromises;
|
|
11
13
|
constructor(tracker: ChatStateTracker);
|
|
12
14
|
/**
|
|
13
15
|
* Get collection of all the spaces you are in.
|
|
@@ -36,7 +38,6 @@ export declare class SpacesManager {
|
|
|
36
38
|
private handleSpaceDeleted;
|
|
37
39
|
private handleSpaceJoined;
|
|
38
40
|
private addJoinedSpaces;
|
|
39
|
-
private handleSpaceLeft;
|
|
40
41
|
private handleSpaceMemberJoined;
|
|
41
42
|
private handleSpaceMemberLeft;
|
|
42
43
|
private handleSpaceMembers;
|
package/package.json
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {IndexedCollection} from "../IndexedObjectCollection";
|
|
2
|
+
|
|
3
|
+
export class DeferredTask {
|
|
4
|
+
public readonly promise: Promise<void>;
|
|
5
|
+
public resolve: () => void;
|
|
6
|
+
|
|
7
|
+
public constructor() {
|
|
8
|
+
this.promise = new Promise<void>((resolve) => this.resolve = resolve);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class PromiseRegistry {
|
|
13
|
+
private promises = new IndexedCollection<string, Promise<any>>();
|
|
14
|
+
|
|
15
|
+
public register<T = any>(promise: Promise<T>, key: string): void {
|
|
16
|
+
this.promises.set([key, promise]);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public registerByFunction(fn: () => Promise<any>, key: string): void {
|
|
20
|
+
this.register(fn(), key);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public get<T = any>(key: string): Promise<T> | undefined {
|
|
24
|
+
return this.promises.get(key);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public has(key: string): boolean {
|
|
28
|
+
return this.promises.has(key);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public notExist(key: string): boolean {
|
|
32
|
+
return ! this.has(key);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public forget(...keys: string[]): void {
|
|
36
|
+
this.promises.delete(...keys);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -3,7 +3,7 @@ import {Session, User} from "pserv-ts-types";
|
|
|
3
3
|
import {RoomsManager} from "./RoomsManager";
|
|
4
4
|
import {SpacesManager} from "./SpacesManager";
|
|
5
5
|
import {PermissionsManager} from "./PermissionsManager";
|
|
6
|
-
import {DeferredTask} from "./
|
|
6
|
+
import {DeferredTask} from "./AsyncUtils";
|
|
7
7
|
|
|
8
8
|
export class ChatStateTracker {
|
|
9
9
|
/**
|
|
@@ -2,19 +2,19 @@ import {ChatStateTracker} from "./ChatStateTracker";
|
|
|
2
2
|
import {
|
|
3
3
|
PermissionOverwrites,
|
|
4
4
|
PermissionOverwritesChanged,
|
|
5
|
-
PermissionOverwritesValue,
|
|
6
|
-
Role
|
|
5
|
+
PermissionOverwritesValue, RoleDeleted, RoomDeleted, RoomLeft, SpaceDeleted, SpaceLeft, TopicDeleted,
|
|
7
6
|
} from "pserv-ts-types";
|
|
8
7
|
import {EventHandler, EventTarget} from "../EventTarget";
|
|
9
8
|
import {IndexedCollection} from "../IndexedObjectCollection";
|
|
10
9
|
import {Permission} from "../Permission";
|
|
10
|
+
import {PromiseRegistry} from "./AsyncUtils";
|
|
11
11
|
|
|
12
12
|
const getOvId = (
|
|
13
13
|
layer: PermissionOverwrites['layer'],
|
|
14
14
|
layerId: PermissionOverwrites['layerId'],
|
|
15
|
-
target
|
|
16
|
-
targetId
|
|
17
|
-
) => layer + (layerId ?? '') + target + targetId;
|
|
15
|
+
target?: PermissionOverwrites['target'],
|
|
16
|
+
targetId?: PermissionOverwrites['targetId'],
|
|
17
|
+
) => layer + (layerId ?? '') + (target ?? '') + (targetId ?? '');
|
|
18
18
|
|
|
19
19
|
const getOvIdByObject = (overwrites: PermissionOverwrites | PermissionOverwritesChanged): string => getOvId(
|
|
20
20
|
overwrites.layer, overwrites.layerId, overwrites.target, overwrites.targetId
|
|
@@ -22,11 +22,18 @@ const getOvIdByObject = (overwrites: PermissionOverwrites | PermissionOverwrites
|
|
|
22
22
|
|
|
23
23
|
export class PermissionsManager extends EventTarget {
|
|
24
24
|
private readonly overwrites = new IndexedCollection<string, PermissionOverwrites>();
|
|
25
|
+
private readonly overwritesPromises = new PromiseRegistry();
|
|
25
26
|
|
|
26
27
|
public constructor(private tracker: ChatStateTracker) {
|
|
27
28
|
super();
|
|
28
29
|
this.tracker.client.on('PermissionOverwrites', ev => this.handlePermissionOverwrites(ev));
|
|
29
30
|
this.tracker.client.on('PermissionOverwritesChanged', ev => this.handlePermissionOverwrites(ev));
|
|
31
|
+
this.tracker.client.on('SpaceDeleted', ev => this.handleSpaceDeleted(ev));
|
|
32
|
+
this.tracker.client.on('SpaceLeft', ev => this.handleSpaceDeleted(ev));
|
|
33
|
+
this.tracker.client.on('RoomDeleted', ev => this.handleRoomDeleted(ev));
|
|
34
|
+
this.tracker.client.on('RoomLeft', ev => this.handleRoomDeleted(ev));
|
|
35
|
+
this.tracker.client.on('TopicDeleted', ev => this.handleTopicDeleted(ev));
|
|
36
|
+
this.tracker.client.on('RoleDeleted', ev => this.handleRoleDeleted(ev));
|
|
30
37
|
}
|
|
31
38
|
|
|
32
39
|
public async getOverwrites(
|
|
@@ -37,16 +44,21 @@ export class PermissionsManager extends EventTarget {
|
|
|
37
44
|
): Promise<PermissionOverwrites | undefined> {
|
|
38
45
|
const id = getOvId(layer, layerId, target, targetId);
|
|
39
46
|
|
|
40
|
-
if (this.
|
|
41
|
-
|
|
47
|
+
if (this.overwritesPromises.notExist(id)) {
|
|
48
|
+
this.overwritesPromises.registerByFunction(async () => {
|
|
49
|
+
const result = await this.tracker.client.send(
|
|
50
|
+
'GetPermissionOverwrites',
|
|
51
|
+
{layer, layerId, target, targetId},
|
|
52
|
+
);
|
|
53
|
+
if (result.error) {
|
|
54
|
+
throw result.error;
|
|
55
|
+
}
|
|
56
|
+
this.handlePermissionOverwrites(result.data);
|
|
57
|
+
}, id);
|
|
42
58
|
}
|
|
43
59
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
{layer, layerId, target, targetId},
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
return result.error ? null : result.data;
|
|
60
|
+
await this.overwritesPromises.get(id);
|
|
61
|
+
return this.overwrites.get(id);
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
public on(eventName: 'change', handler: EventHandler<any>): this {
|
|
@@ -113,11 +125,46 @@ export class PermissionsManager extends EventTarget {
|
|
|
113
125
|
return this.resolveOverwritesHierarchy(await Promise.all(promises));
|
|
114
126
|
}
|
|
115
127
|
|
|
116
|
-
private handlePermissionOverwrites(ev: PermissionOverwritesChanged | PermissionOverwrites) {
|
|
128
|
+
private handlePermissionOverwrites(ev: PermissionOverwritesChanged | PermissionOverwrites): void {
|
|
117
129
|
this.overwrites.set([getOvIdByObject(ev), ev]);
|
|
118
130
|
this.emit('change');
|
|
119
131
|
}
|
|
120
132
|
|
|
133
|
+
private handleSpaceDeleted(ev: SpaceDeleted | SpaceLeft): void {
|
|
134
|
+
const ids = this.deleteOverwritesByIdPrefix(getOvId('Space', ev.id));
|
|
135
|
+
this.overwritesPromises.forget(...ids);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private handleRoomDeleted(ev: RoomDeleted | RoomLeft): void {
|
|
139
|
+
const ids = this.deleteOverwritesByIdPrefix(getOvId('Room', ev.id));
|
|
140
|
+
this.overwritesPromises.forget(...ids);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private handleTopicDeleted(ev: TopicDeleted): void {
|
|
144
|
+
const ids = this.deleteOverwritesByIdPrefix(getOvId('Topic', ev.id));
|
|
145
|
+
this.overwritesPromises.forget(...ids);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private handleRoleDeleted(ev: RoleDeleted): void {
|
|
149
|
+
const ids = this.deleteOverwritesByIdPrefix(getOvId('Space', ev.spaceId, 'Role', ev.id));
|
|
150
|
+
this.overwritesPromises.forget(...ids);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @return Matched and deleted ids
|
|
155
|
+
*/
|
|
156
|
+
private deleteOverwritesByIdPrefix(prefix: string): string[] {
|
|
157
|
+
const ids: string[] = [];
|
|
158
|
+
this.overwrites.items.forEach((overwrites) => {
|
|
159
|
+
const id = getOvIdByObject(overwrites);
|
|
160
|
+
if (id.startsWith(prefix)) {
|
|
161
|
+
ids.push(id);
|
|
162
|
+
this.overwrites.delete(id);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
return ids;
|
|
166
|
+
}
|
|
167
|
+
|
|
121
168
|
private async collectRoleOverwrites(
|
|
122
169
|
spaceId: string,
|
|
123
170
|
layer: PermissionOverwrites['layer'],
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {IndexedCollection, ObservableIndexedObjectCollection} from "../IndexedObjectCollection";
|
|
2
2
|
import {
|
|
3
3
|
NewTopic,
|
|
4
|
-
Room,
|
|
4
|
+
Room, RoomDeleted,
|
|
5
5
|
RoomJoined, RoomLeft,
|
|
6
6
|
RoomMember, RoomMemberJoined, RoomMemberLeft, RoomMembers,
|
|
7
|
-
RoomMemberUpdated, Session,
|
|
7
|
+
RoomMemberUpdated, Session, SpaceDeleted, SpaceMemberLeft,
|
|
8
8
|
SpaceMemberUpdated,
|
|
9
9
|
Topic,
|
|
10
10
|
TopicDeleted,
|
|
11
11
|
UserChanged,
|
|
12
12
|
} from "pserv-ts-types";
|
|
13
13
|
import {ChatStateTracker} from "./ChatStateTracker";
|
|
14
|
-
import {DeferredTask} from "./
|
|
14
|
+
import {DeferredTask, PromiseRegistry} from "./AsyncUtils";
|
|
15
15
|
import {MessagesManager} from "./MessagesManager";
|
|
16
16
|
|
|
17
17
|
export class RoomsManager {
|
|
@@ -21,6 +21,7 @@ export class RoomsManager {
|
|
|
21
21
|
private readonly topics = new IndexedCollection<string, ObservableIndexedObjectCollection<Topic>>();
|
|
22
22
|
private readonly members = new IndexedCollection<string, ObservableIndexedObjectCollection<RoomMember>>();
|
|
23
23
|
private readonly deferredSession = new DeferredTask();
|
|
24
|
+
private readonly membersPromises = new PromiseRegistry();
|
|
24
25
|
|
|
25
26
|
public constructor(private tracker: ChatStateTracker) {
|
|
26
27
|
this.messages = new MessagesManager(tracker);
|
|
@@ -29,11 +30,14 @@ export class RoomsManager {
|
|
|
29
30
|
this.tracker.client.on('TopicDeleted', ev => this.handleTopicDeleted(ev));
|
|
30
31
|
this.tracker.client.on('RoomJoined', ev => this.handleRoomJoined(ev));
|
|
31
32
|
this.tracker.client.on('RoomLeft', ev => this.handleRoomLeft(ev));
|
|
33
|
+
this.tracker.client.on('RoomDeleted', ev => this.handleRoomDeleted(ev));
|
|
32
34
|
this.tracker.client.on('RoomMemberJoined', ev => this.handleRoomMemberJoined(ev));
|
|
33
35
|
this.tracker.client.on('RoomMemberLeft', ev => this.handleRoomMemberLeft(ev));
|
|
34
36
|
this.tracker.client.on('RoomMembers', ev => this.handleRoomMembers(ev));
|
|
35
37
|
this.tracker.client.on('RoomMemberUpdated', ev => this.handleRoomMemberUpdated(ev));
|
|
38
|
+
this.tracker.client.on('SpaceMemberLeft', ev => this.handleSpaceMemberLeft(ev));
|
|
36
39
|
this.tracker.client.on('SpaceMemberUpdated', ev => this.handleSpaceMemberUpdated(ev));
|
|
40
|
+
this.tracker.client.on('SpaceDeleted', ev => this.handleSpaceDeleted(ev));
|
|
37
41
|
this.tracker.client.on('UserChanged', ev => this.handleUserChanged(ev));
|
|
38
42
|
this.tracker.client.on('Session', ev => this.handleSession(ev));
|
|
39
43
|
}
|
|
@@ -42,16 +46,17 @@ export class RoomsManager {
|
|
|
42
46
|
* Get collection of room members.
|
|
43
47
|
*/
|
|
44
48
|
public async getMembers(roomId: string): Promise<ObservableIndexedObjectCollection<RoomMember> | undefined> {
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
if (this.membersPromises.notExist(roomId)) {
|
|
50
|
+
this.membersPromises.registerByFunction(async () => {
|
|
51
|
+
const result = await this.tracker.client.send('GetRoomMembers', {id: roomId});
|
|
52
|
+
if (result.error) {
|
|
53
|
+
throw result.error;
|
|
54
|
+
}
|
|
55
|
+
this.handleRoomMembers(result.data);
|
|
56
|
+
}, roomId);
|
|
53
57
|
}
|
|
54
58
|
|
|
59
|
+
await this.membersPromises.get(roomId);
|
|
55
60
|
return this.members.get(roomId);
|
|
56
61
|
}
|
|
57
62
|
|
|
@@ -86,13 +91,10 @@ export class RoomsManager {
|
|
|
86
91
|
return this.topics.get(roomId);
|
|
87
92
|
}
|
|
88
93
|
|
|
89
|
-
|
|
90
|
-
* For internal use. If you want to leave the room, execute a proper command on client object.
|
|
91
|
-
* @internal
|
|
92
|
-
*/
|
|
93
|
-
public _delete(...roomIds: string[]): void {
|
|
94
|
+
private deleteRoom(...roomIds: string[]): void {
|
|
94
95
|
this.list.delete(...roomIds);
|
|
95
96
|
this.members.delete(...roomIds);
|
|
97
|
+
this.membersPromises.forget(...roomIds);
|
|
96
98
|
|
|
97
99
|
for (const roomId of roomIds) {
|
|
98
100
|
const topicIds: string[] = this.topics.get(roomId)?.map(topic => topic.id) ?? [];
|
|
@@ -102,12 +104,8 @@ export class RoomsManager {
|
|
|
102
104
|
this.topics.delete(...roomIds);
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
* @internal
|
|
108
|
-
*/
|
|
109
|
-
public _deleteBySpaceId(spaceId: string): void {
|
|
110
|
-
this._delete(
|
|
107
|
+
private deleteRoomsBySpaceId(spaceId: string): void {
|
|
108
|
+
this.deleteRoom(
|
|
111
109
|
...this.list.findBy('spaceId', spaceId).map(room => room.id)
|
|
112
110
|
);
|
|
113
111
|
}
|
|
@@ -132,6 +130,10 @@ export class RoomsManager {
|
|
|
132
130
|
}
|
|
133
131
|
}
|
|
134
132
|
|
|
133
|
+
private handleSpaceMemberLeft(ev: SpaceMemberLeft): void {
|
|
134
|
+
this.deleteRoomsBySpaceId(ev.spaceId);
|
|
135
|
+
}
|
|
136
|
+
|
|
135
137
|
private handleRoomMemberUpdated(ev: RoomMemberUpdated): void {
|
|
136
138
|
if (! this.members.has(ev.roomId)) {
|
|
137
139
|
// We do not track member list for this room.
|
|
@@ -152,6 +154,10 @@ export class RoomsManager {
|
|
|
152
154
|
members.set(newMember);
|
|
153
155
|
}
|
|
154
156
|
|
|
157
|
+
private handleSpaceDeleted(ev: SpaceDeleted): void {
|
|
158
|
+
this.deleteRoomsBySpaceId(ev.id);
|
|
159
|
+
}
|
|
160
|
+
|
|
155
161
|
private handleTopicDeleted(ev: TopicDeleted): void {
|
|
156
162
|
const collection = this.topics.get(ev.roomId);
|
|
157
163
|
collection.delete(ev.id);
|
|
@@ -177,6 +183,10 @@ export class RoomsManager {
|
|
|
177
183
|
this.addJoinedRooms(ev.room);
|
|
178
184
|
}
|
|
179
185
|
|
|
186
|
+
private handleRoomDeleted(ev: RoomDeleted): void {
|
|
187
|
+
this.deleteRoom(ev.id);
|
|
188
|
+
}
|
|
189
|
+
|
|
180
190
|
private addJoinedRooms(...rooms: Room[]): void {
|
|
181
191
|
for (const room of rooms) {
|
|
182
192
|
this.addJoinedRoomTopics(room.id, ...room.topics);
|
|
@@ -185,7 +195,7 @@ export class RoomsManager {
|
|
|
185
195
|
}
|
|
186
196
|
|
|
187
197
|
private handleRoomLeft(ev: RoomLeft): void {
|
|
188
|
-
this.
|
|
198
|
+
this.deleteRoom(ev.id);
|
|
189
199
|
}
|
|
190
200
|
|
|
191
201
|
private handleRoomMemberJoined(ev: RoomMemberJoined): void {
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
SpaceDeleted, SpaceJoined, SpaceLeft,
|
|
11
11
|
SpaceMember, SpaceMemberJoined, SpaceMemberLeft, SpaceMembers, SpaceMemberUpdated, SpaceRooms, UserChanged
|
|
12
12
|
} from "pserv-ts-types";
|
|
13
|
-
import {DeferredTask} from "./
|
|
13
|
+
import {DeferredTask, PromiseRegistry} from "./AsyncUtils";
|
|
14
14
|
import {reorderRolesOnPriorityUpdate} from "./functions";
|
|
15
15
|
|
|
16
16
|
export class SpacesManager {
|
|
@@ -19,13 +19,15 @@ export class SpacesManager {
|
|
|
19
19
|
private readonly rooms = new IndexedCollection<string, ObservableIndexedObjectCollection<RoomSummary>>();
|
|
20
20
|
private readonly members = new IndexedCollection<string, ObservableIndexedObjectCollection<SpaceMember>>();
|
|
21
21
|
private readonly deferredSession = new DeferredTask();
|
|
22
|
+
private readonly roomsPromises = new PromiseRegistry();
|
|
23
|
+
private readonly membersPromises = new PromiseRegistry();
|
|
22
24
|
|
|
23
25
|
public constructor(private tracker: ChatStateTracker) {
|
|
24
26
|
this.tracker.client.on('NewRoom', ev => this.handleNewRoom(ev));
|
|
25
27
|
this.tracker.client.on('RoomDeleted', ev => this.handleRoomDeleted(ev));
|
|
26
28
|
this.tracker.client.on('SpaceDeleted', ev => this.handleSpaceDeleted(ev));
|
|
27
29
|
this.tracker.client.on('SpaceJoined', ev => this.handleSpaceJoined(ev));
|
|
28
|
-
this.tracker.client.on('SpaceLeft', ev => this.
|
|
30
|
+
this.tracker.client.on('SpaceLeft', ev => this.handleSpaceDeleted(ev));
|
|
29
31
|
this.tracker.client.on('SpaceMemberJoined', ev => this.handleSpaceMemberJoined(ev));
|
|
30
32
|
this.tracker.client.on('SpaceMemberLeft', ev => this.handleSpaceMemberLeft(ev));
|
|
31
33
|
this.tracker.client.on('SpaceMembers', ev => this.handleSpaceMembers(ev));
|
|
@@ -58,16 +60,17 @@ export class SpacesManager {
|
|
|
58
60
|
* Get collection of the all available rooms inside given space.
|
|
59
61
|
*/
|
|
60
62
|
public async getRooms(spaceId: string): Promise<ObservableIndexedObjectCollection<RoomSummary> | undefined> {
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
if (this.roomsPromises.notExist(spaceId)) {
|
|
64
|
+
this.roomsPromises.registerByFunction(async () => {
|
|
65
|
+
const result = await this.tracker.client.send('GetSpaceRooms', {id: spaceId});
|
|
66
|
+
if (result.error) {
|
|
67
|
+
throw result.error;
|
|
68
|
+
}
|
|
69
|
+
this.handleSpaceRooms(result.data);
|
|
70
|
+
}, spaceId);
|
|
69
71
|
}
|
|
70
72
|
|
|
73
|
+
await this.roomsPromises.get(spaceId);
|
|
71
74
|
return this.rooms.get(spaceId);
|
|
72
75
|
}
|
|
73
76
|
|
|
@@ -75,16 +78,17 @@ export class SpacesManager {
|
|
|
75
78
|
* Get collection of space members.
|
|
76
79
|
*/
|
|
77
80
|
public async getMembers(spaceId: string): Promise<ObservableIndexedObjectCollection<SpaceMember> | undefined> {
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
if (this.membersPromises.notExist(spaceId)) {
|
|
82
|
+
this.membersPromises.registerByFunction(async () => {
|
|
83
|
+
const result = await this.tracker.client.send('GetSpaceMembers', {id: spaceId});
|
|
84
|
+
if (result.error) {
|
|
85
|
+
throw result.error;
|
|
86
|
+
}
|
|
87
|
+
this.handleSpaceMembers(result.data);
|
|
88
|
+
}, spaceId);
|
|
86
89
|
}
|
|
87
90
|
|
|
91
|
+
await this.membersPromises.get(spaceId);
|
|
88
92
|
return this.members.get(spaceId);
|
|
89
93
|
}
|
|
90
94
|
|
|
@@ -117,8 +121,6 @@ export class SpacesManager {
|
|
|
117
121
|
if (ev.spaceId) {
|
|
118
122
|
this.rooms.get(ev.spaceId).delete(ev.id);
|
|
119
123
|
}
|
|
120
|
-
|
|
121
|
-
this.tracker.rooms._delete(ev.id);
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
private handleRoleDeleted(ev: RoleDeleted): void {
|
|
@@ -127,11 +129,12 @@ export class SpacesManager {
|
|
|
127
129
|
this.list.get(ev.spaceId).roles = collection.items;
|
|
128
130
|
}
|
|
129
131
|
|
|
130
|
-
private handleSpaceDeleted(ev: SpaceDeleted): void {
|
|
131
|
-
this.tracker.rooms._deleteBySpaceId(ev.id);
|
|
132
|
+
private handleSpaceDeleted(ev: SpaceDeleted | SpaceLeft): void {
|
|
132
133
|
this.roles.delete(ev.id);
|
|
133
134
|
this.members.delete(ev.id);
|
|
135
|
+
this.membersPromises.forget(ev.id);
|
|
134
136
|
this.rooms.delete(ev.id);
|
|
137
|
+
this.roomsPromises.forget(ev.id);
|
|
135
138
|
this.list.delete(ev.id);
|
|
136
139
|
}
|
|
137
140
|
|
|
@@ -147,10 +150,6 @@ export class SpacesManager {
|
|
|
147
150
|
this.list.set(...spaces);
|
|
148
151
|
}
|
|
149
152
|
|
|
150
|
-
private handleSpaceLeft(ev: SpaceLeft): void {
|
|
151
|
-
this.handleSpaceDeleted(ev);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
153
|
private handleSpaceMemberJoined(ev: SpaceMemberJoined): void {
|
|
155
154
|
if (this.members.has(ev.spaceId)) {
|
|
156
155
|
this.members.get(ev.spaceId).set(ev.member);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {PromiseRegistry} from "../src/state-tracker/AsyncUtils";
|
|
2
|
+
|
|
3
|
+
test('promise registry - limit the calling of async process', async () => {
|
|
4
|
+
const pr = new PromiseRegistry();
|
|
5
|
+
let generationCount = 0;
|
|
6
|
+
|
|
7
|
+
async function generateResult() {
|
|
8
|
+
return ++generationCount;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async function getResult() {
|
|
12
|
+
const resultKey = 'test';
|
|
13
|
+
|
|
14
|
+
if (pr.notExist('test')) {
|
|
15
|
+
pr.registerByFunction(generateResult, resultKey);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
await pr.get(resultKey);
|
|
19
|
+
return generationCount;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const call1 = await getResult();
|
|
23
|
+
expect(call1).toBe(1);
|
|
24
|
+
const call2 = await getResult();
|
|
25
|
+
expect(call2).toBe(1);
|
|
26
|
+
const call3 = await getResult();
|
|
27
|
+
expect(call3).toBe(1);
|
|
28
|
+
|
|
29
|
+
expect(generationCount).toBe(1);
|
|
30
|
+
});
|