polfan-server-js-client 0.1.99941 → 0.2.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/.idea/modules.xml +8 -0
- package/.idea/polfan-js-client-library.iml +8 -0
- package/.idea/workspace.xml +35 -10
- package/build/index.cjs.js +2252 -0
- package/build/index.cjs.js.map +1 -0
- package/build/index.umd.js +2 -0
- package/build/index.umd.js.map +1 -0
- package/build/types/index.d.ts +2 -2
- package/package.json +15 -5
- package/src/index.ts +6 -3
- package/webpack.config.browser.js +59 -0
- package/webpack.config.node.js +47 -0
- package/webpack.config.demo.js +0 -47
- package/webpack.config.js +0 -69
|
@@ -0,0 +1,2252 @@
|
|
|
1
|
+
/******/ (() => { // webpackBootstrap
|
|
2
|
+
/******/ "use strict";
|
|
3
|
+
/******/ // The require scope
|
|
4
|
+
/******/ var __webpack_require__ = {};
|
|
5
|
+
/******/
|
|
6
|
+
/************************************************************************/
|
|
7
|
+
/******/ /* webpack/runtime/define property getters */
|
|
8
|
+
/******/ (() => {
|
|
9
|
+
/******/ // define getter functions for harmony exports
|
|
10
|
+
/******/ __webpack_require__.d = (exports, definition) => {
|
|
11
|
+
/******/ for(var key in definition) {
|
|
12
|
+
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
13
|
+
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
14
|
+
/******/ }
|
|
15
|
+
/******/ }
|
|
16
|
+
/******/ };
|
|
17
|
+
/******/ })();
|
|
18
|
+
/******/
|
|
19
|
+
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
20
|
+
/******/ (() => {
|
|
21
|
+
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
22
|
+
/******/ })();
|
|
23
|
+
/******/
|
|
24
|
+
/******/ /* webpack/runtime/make namespace object */
|
|
25
|
+
/******/ (() => {
|
|
26
|
+
/******/ // define __esModule on exports
|
|
27
|
+
/******/ __webpack_require__.r = (exports) => {
|
|
28
|
+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
29
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
30
|
+
/******/ }
|
|
31
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
32
|
+
/******/ };
|
|
33
|
+
/******/ })();
|
|
34
|
+
/******/
|
|
35
|
+
/************************************************************************/
|
|
36
|
+
var __webpack_exports__ = {};
|
|
37
|
+
// ESM COMPAT FLAG
|
|
38
|
+
__webpack_require__.r(__webpack_exports__);
|
|
39
|
+
|
|
40
|
+
// EXPORTS
|
|
41
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
42
|
+
"AuthClient": () => (/* reexport */ AuthClient),
|
|
43
|
+
"FilesClient": () => (/* reexport */ FilesClient),
|
|
44
|
+
"IndexedCollection": () => (/* reexport */ IndexedCollection),
|
|
45
|
+
"IndexedObjectCollection": () => (/* reexport */ IndexedObjectCollection),
|
|
46
|
+
"Layer": () => (/* reexport */ Layer),
|
|
47
|
+
"ObservableIndexedCollection": () => (/* reexport */ ObservableIndexedCollection),
|
|
48
|
+
"ObservableIndexedObjectCollection": () => (/* reexport */ ObservableIndexedObjectCollection),
|
|
49
|
+
"PermissionDefinition": () => (/* reexport */ PermissionDefinition),
|
|
50
|
+
"Permissions": () => (/* reexport */ Permissions),
|
|
51
|
+
"WebApiChatClient": () => (/* reexport */ WebApiChatClient),
|
|
52
|
+
"WebSocketChatClient": () => (/* reexport */ WebSocketChatClient),
|
|
53
|
+
"extractUserFromMember": () => (/* reexport */ extractUserFromMember)
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
;// CONCATENATED MODULE: ./src/EventTarget.ts
|
|
57
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
58
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
59
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
60
|
+
class EventTarget {
|
|
61
|
+
constructor() {
|
|
62
|
+
_defineProperty(this, "events", new Map());
|
|
63
|
+
_defineProperty(this, "onceEvents", new Map());
|
|
64
|
+
}
|
|
65
|
+
on(eventName, handler) {
|
|
66
|
+
this.addHandler(this.events, eventName, handler);
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
once(eventName, handler) {
|
|
70
|
+
this.addHandler(this.onceEvents, eventName, handler);
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
off(eventName, handler) {
|
|
74
|
+
const index = this.events.get(eventName)?.indexOf(handler);
|
|
75
|
+
if (!index || index < 0) {
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
this.events.get(eventName).splice(index, 1);
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
emit(eventName, event) {
|
|
82
|
+
this.callHandlers(this.events, eventName, event);
|
|
83
|
+
this.callHandlers(this.onceEvents, eventName, event);
|
|
84
|
+
this.onceEvents.delete(eventName);
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
addHandler(map, eventName, handler) {
|
|
88
|
+
const handlers = map.get(eventName) ?? [];
|
|
89
|
+
handlers.push(handler);
|
|
90
|
+
map.set(eventName, handlers);
|
|
91
|
+
}
|
|
92
|
+
callHandlers(map, eventName, event) {
|
|
93
|
+
map.get(eventName)?.forEach(callback => callback(event));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
;// CONCATENATED MODULE: ./src/AbstractChatClient.ts
|
|
97
|
+
function AbstractChatClient_defineProperty(obj, key, value) { key = AbstractChatClient_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
98
|
+
function AbstractChatClient_toPropertyKey(arg) { var key = AbstractChatClient_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
99
|
+
function AbstractChatClient_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
100
|
+
|
|
101
|
+
class AbstractChatClient extends EventTarget {
|
|
102
|
+
constructor(...args) {
|
|
103
|
+
super(...args);
|
|
104
|
+
AbstractChatClient_defineProperty(this, "awaitingResponse", new Map());
|
|
105
|
+
AbstractChatClient_defineProperty(this, "sentCounter", 0);
|
|
106
|
+
}
|
|
107
|
+
on(eventName, handler) {
|
|
108
|
+
return super.on(eventName, handler);
|
|
109
|
+
}
|
|
110
|
+
once(eventName, handler) {
|
|
111
|
+
return super.once(eventName, handler);
|
|
112
|
+
}
|
|
113
|
+
createEnvelope(type, data) {
|
|
114
|
+
return {
|
|
115
|
+
type,
|
|
116
|
+
data,
|
|
117
|
+
ref: (++this.sentCounter).toString()
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
createPromiseFromCommandEnvelope(envelope) {
|
|
121
|
+
return new Promise((...args) => this.awaitingResponse.set(envelope.ref, args));
|
|
122
|
+
}
|
|
123
|
+
handleIncomingEnvelope(envelope) {
|
|
124
|
+
if (!this.awaitingResponse.has(envelope.ref)) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const isError = envelope.type === 'Error';
|
|
128
|
+
this.awaitingResponse.get(envelope.ref)[0]({
|
|
129
|
+
data: isError ? null : envelope.data,
|
|
130
|
+
error: isError ? envelope.data : null
|
|
131
|
+
});
|
|
132
|
+
this.awaitingResponse.delete(envelope.ref);
|
|
133
|
+
}
|
|
134
|
+
handleEnvelopeSendError(envelope, error) {
|
|
135
|
+
if (!this.awaitingResponse.has(envelope.ref)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
this.awaitingResponse.get(envelope.ref)[0](error);
|
|
139
|
+
this.awaitingResponse.delete(envelope.ref);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Map of incoming events.
|
|
145
|
+
*/
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Map of commands and their corresponding events.
|
|
149
|
+
*/
|
|
150
|
+
;// CONCATENATED MODULE: ./src/IndexedObjectCollection.ts
|
|
151
|
+
function IndexedObjectCollection_defineProperty(obj, key, value) { key = IndexedObjectCollection_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
152
|
+
function IndexedObjectCollection_toPropertyKey(arg) { var key = IndexedObjectCollection_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
153
|
+
function IndexedObjectCollection_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
154
|
+
|
|
155
|
+
class IndexedCollection {
|
|
156
|
+
constructor(items = []) {
|
|
157
|
+
IndexedObjectCollection_defineProperty(this, "_items", new Map());
|
|
158
|
+
IndexedObjectCollection_defineProperty(this, "_mutationCounter", 0);
|
|
159
|
+
this.set(...items);
|
|
160
|
+
}
|
|
161
|
+
get mutationCounter() {
|
|
162
|
+
return this._mutationCounter;
|
|
163
|
+
}
|
|
164
|
+
get items() {
|
|
165
|
+
return this._items;
|
|
166
|
+
}
|
|
167
|
+
get length() {
|
|
168
|
+
return this._items.size;
|
|
169
|
+
}
|
|
170
|
+
set(...items) {
|
|
171
|
+
this._mutationCounter++;
|
|
172
|
+
for (const item of items) {
|
|
173
|
+
this._items.set(item[0], item[1]);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
get(id) {
|
|
177
|
+
return this.items.get(id);
|
|
178
|
+
}
|
|
179
|
+
has(id) {
|
|
180
|
+
return this.items.has(id);
|
|
181
|
+
}
|
|
182
|
+
delete(...ids) {
|
|
183
|
+
for (const id of ids) {
|
|
184
|
+
this.items.delete(id);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
deleteAll() {
|
|
188
|
+
this.items.clear();
|
|
189
|
+
}
|
|
190
|
+
findBy(field, valueToFind, limit = null) {
|
|
191
|
+
const result = new IndexedCollection();
|
|
192
|
+
let item;
|
|
193
|
+
while (!(item = this.items.entries().next().value).done) {
|
|
194
|
+
if (limit && result.length === limit) {
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
if (item[1][field] === valueToFind) {
|
|
198
|
+
result.set(item);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
class IndexedObjectCollection {
|
|
205
|
+
constructor(id, items = []) {
|
|
206
|
+
this.id = id;
|
|
207
|
+
IndexedObjectCollection_defineProperty(this, "_items", void 0);
|
|
208
|
+
this._items = new IndexedCollection();
|
|
209
|
+
this.set(...items);
|
|
210
|
+
}
|
|
211
|
+
get items() {
|
|
212
|
+
return Array.from(this._items.items.values());
|
|
213
|
+
}
|
|
214
|
+
get length() {
|
|
215
|
+
return this._items.length;
|
|
216
|
+
}
|
|
217
|
+
get mutationCounter() {
|
|
218
|
+
return this._items.mutationCounter;
|
|
219
|
+
}
|
|
220
|
+
set(...items) {
|
|
221
|
+
this._items.set(...items.map(item => [this.getId(item), item]));
|
|
222
|
+
}
|
|
223
|
+
get(id) {
|
|
224
|
+
return this._items.get(id);
|
|
225
|
+
}
|
|
226
|
+
getAt(index) {
|
|
227
|
+
return this.items[index];
|
|
228
|
+
}
|
|
229
|
+
has(id) {
|
|
230
|
+
return this._items.has(id);
|
|
231
|
+
}
|
|
232
|
+
delete(...ids) {
|
|
233
|
+
this._items.delete(...ids);
|
|
234
|
+
}
|
|
235
|
+
deleteAll() {
|
|
236
|
+
this._items.deleteAll();
|
|
237
|
+
}
|
|
238
|
+
findBy(field, valueToFind, limit = null) {
|
|
239
|
+
const result = new IndexedObjectCollection(this.id);
|
|
240
|
+
for (const value of this.items) {
|
|
241
|
+
if (limit && result.length === limit) {
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
if (value[field] === valueToFind) {
|
|
245
|
+
result.set(value);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return result;
|
|
249
|
+
}
|
|
250
|
+
getId(item) {
|
|
251
|
+
return typeof this.id === 'function' ? this.id(item) : item[this.id];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
class ObservableIndexedCollection extends IndexedCollection {
|
|
255
|
+
constructor(items = []) {
|
|
256
|
+
super();
|
|
257
|
+
IndexedObjectCollection_defineProperty(this, "eventTarget", void 0);
|
|
258
|
+
this.eventTarget = new EventTarget();
|
|
259
|
+
this.set(...items);
|
|
260
|
+
}
|
|
261
|
+
set(...items) {
|
|
262
|
+
if (items.length) {
|
|
263
|
+
super.set(...items);
|
|
264
|
+
this.eventTarget.emit('change', {
|
|
265
|
+
setItems: items.map(item => item[0])
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
delete(...ids) {
|
|
270
|
+
if (ids.length) {
|
|
271
|
+
super.delete(...ids);
|
|
272
|
+
this.eventTarget.emit('change', {
|
|
273
|
+
deletedItems: ids
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
deleteAll() {
|
|
278
|
+
if (this.length) {
|
|
279
|
+
const ids = this._items.keys();
|
|
280
|
+
super.deleteAll();
|
|
281
|
+
this.eventTarget.emit('change', {
|
|
282
|
+
deletedItems: Array.from(ids)
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
on(eventName, handler) {
|
|
287
|
+
this.eventTarget.on(eventName, handler);
|
|
288
|
+
return this;
|
|
289
|
+
}
|
|
290
|
+
once(eventName, handler) {
|
|
291
|
+
this.eventTarget.once(eventName, handler);
|
|
292
|
+
return this;
|
|
293
|
+
}
|
|
294
|
+
off(eventName, handler) {
|
|
295
|
+
this.eventTarget.off(eventName, handler);
|
|
296
|
+
return this;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
class ObservableIndexedObjectCollection extends IndexedObjectCollection {
|
|
300
|
+
constructor(id, items = []) {
|
|
301
|
+
super(id);
|
|
302
|
+
this.id = id;
|
|
303
|
+
IndexedObjectCollection_defineProperty(this, "eventTarget", void 0);
|
|
304
|
+
this.eventTarget = new EventTarget();
|
|
305
|
+
this.set(...items);
|
|
306
|
+
}
|
|
307
|
+
set(...items) {
|
|
308
|
+
if (items.length) {
|
|
309
|
+
super.set(...items);
|
|
310
|
+
this.eventTarget.emit('change', {
|
|
311
|
+
setItems: items.map(item => this.getId(item))
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
delete(...ids) {
|
|
316
|
+
if (ids.length) {
|
|
317
|
+
super.delete(...ids);
|
|
318
|
+
this.eventTarget.emit('change', {
|
|
319
|
+
deletedItems: ids
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
deleteAll() {
|
|
324
|
+
if (this.length) {
|
|
325
|
+
const ids = this._items.items.keys();
|
|
326
|
+
super.deleteAll();
|
|
327
|
+
this.eventTarget.emit('change', {
|
|
328
|
+
deletedItems: Array.from(ids)
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
on(eventName, handler) {
|
|
333
|
+
this.eventTarget.on(eventName, handler);
|
|
334
|
+
return this;
|
|
335
|
+
}
|
|
336
|
+
once(eventName, handler) {
|
|
337
|
+
this.eventTarget.once(eventName, handler);
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
off(eventName, handler) {
|
|
341
|
+
this.eventTarget.off(eventName, handler);
|
|
342
|
+
return this;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
;// CONCATENATED MODULE: ./src/state-tracker/AsyncUtils.ts
|
|
346
|
+
function AsyncUtils_defineProperty(obj, key, value) { key = AsyncUtils_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
347
|
+
function AsyncUtils_toPropertyKey(arg) { var key = AsyncUtils_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
348
|
+
function AsyncUtils_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
349
|
+
|
|
350
|
+
class DeferredTask {
|
|
351
|
+
constructor() {
|
|
352
|
+
AsyncUtils_defineProperty(this, "promise", void 0);
|
|
353
|
+
AsyncUtils_defineProperty(this, "resolve", void 0);
|
|
354
|
+
this.promise = new Promise(resolve => this.resolve = resolve);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
class PromiseRegistry {
|
|
358
|
+
constructor() {
|
|
359
|
+
AsyncUtils_defineProperty(this, "promises", new IndexedCollection());
|
|
360
|
+
}
|
|
361
|
+
register(promise, key) {
|
|
362
|
+
this.promises.set([key, promise]);
|
|
363
|
+
}
|
|
364
|
+
registerByFunction(fn, key) {
|
|
365
|
+
this.register(fn(), key);
|
|
366
|
+
}
|
|
367
|
+
get(key) {
|
|
368
|
+
return this.promises.get(key);
|
|
369
|
+
}
|
|
370
|
+
has(key) {
|
|
371
|
+
return this.promises.has(key);
|
|
372
|
+
}
|
|
373
|
+
notExist(key) {
|
|
374
|
+
return !this.has(key);
|
|
375
|
+
}
|
|
376
|
+
forget(...keys) {
|
|
377
|
+
this.promises.delete(...keys);
|
|
378
|
+
}
|
|
379
|
+
forgetAll() {
|
|
380
|
+
this.promises.deleteAll();
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
;// CONCATENATED MODULE: ./src/state-tracker/TopicHistoryWindow.ts
|
|
384
|
+
function TopicHistoryWindow_defineProperty(obj, key, value) { key = TopicHistoryWindow_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
385
|
+
function TopicHistoryWindow_toPropertyKey(arg) { var key = TopicHistoryWindow_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
386
|
+
function TopicHistoryWindow_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
387
|
+
|
|
388
|
+
let WindowState = /*#__PURE__*/function (WindowState) {
|
|
389
|
+
/**
|
|
390
|
+
* The latest messages (those received live) are available in the history window, history has not been fetched.
|
|
391
|
+
*/
|
|
392
|
+
WindowState[WindowState["LIVE"] = 0] = "LIVE";
|
|
393
|
+
/**
|
|
394
|
+
* The latest messages has been fetched and are available in the history window.
|
|
395
|
+
*/
|
|
396
|
+
WindowState[WindowState["LATEST"] = 1] = "LATEST";
|
|
397
|
+
/**
|
|
398
|
+
* The historical messages have been fetched and are available in the history window.
|
|
399
|
+
* Latest messages are not available and will not be available.
|
|
400
|
+
*/
|
|
401
|
+
WindowState[WindowState["PAST"] = 2] = "PAST";
|
|
402
|
+
/**
|
|
403
|
+
* The oldest messages have been fetched and are available in the history window.
|
|
404
|
+
* Next attempts to fetch previous messages will result with no-op.
|
|
405
|
+
*/
|
|
406
|
+
WindowState[WindowState["OLDEST"] = 3] = "OLDEST";
|
|
407
|
+
return WindowState;
|
|
408
|
+
}({});
|
|
409
|
+
class TraversableRemoteCollection extends ObservableIndexedObjectCollection {
|
|
410
|
+
constructor(...args) {
|
|
411
|
+
super(...args);
|
|
412
|
+
/**
|
|
413
|
+
* Maximum numer of items stored in window.
|
|
414
|
+
* Null for unlimited.
|
|
415
|
+
*/
|
|
416
|
+
TopicHistoryWindow_defineProperty(this, "limit", 50);
|
|
417
|
+
TopicHistoryWindow_defineProperty(this, "currentState", WindowState.LIVE);
|
|
418
|
+
TopicHistoryWindow_defineProperty(this, "fetchingState", undefined);
|
|
419
|
+
TopicHistoryWindow_defineProperty(this, "oldestId", null);
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Current mode od collection window. To change mode, call one of available fetch methods.
|
|
423
|
+
*/
|
|
424
|
+
get state() {
|
|
425
|
+
return this.currentState;
|
|
426
|
+
}
|
|
427
|
+
get hasLatest() {
|
|
428
|
+
return [WindowState.LATEST, WindowState.LIVE].includes(this.state);
|
|
429
|
+
}
|
|
430
|
+
get hasOldest() {
|
|
431
|
+
return this.state === WindowState.OLDEST || this.oldestId !== null && this.has(this.oldestId);
|
|
432
|
+
}
|
|
433
|
+
async resetToLatest() {
|
|
434
|
+
if (this.fetchingState || this.currentState === WindowState.LATEST) {
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
this.fetchingState = WindowState.LATEST;
|
|
438
|
+
let result;
|
|
439
|
+
try {
|
|
440
|
+
result = await this.fetchLatestItems();
|
|
441
|
+
} finally {
|
|
442
|
+
this.fetchingState = undefined;
|
|
443
|
+
}
|
|
444
|
+
this.deleteAll();
|
|
445
|
+
this.addItems(result, 'tail');
|
|
446
|
+
this.currentState = WindowState.LATEST;
|
|
447
|
+
}
|
|
448
|
+
async fetchPrevious() {
|
|
449
|
+
if (this.fetchingState || this.hasOldest) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
this.fetchingState = WindowState.PAST;
|
|
453
|
+
let result;
|
|
454
|
+
try {
|
|
455
|
+
result = await this.fetchItemsBefore();
|
|
456
|
+
} finally {
|
|
457
|
+
this.fetchingState = undefined;
|
|
458
|
+
}
|
|
459
|
+
if (!result) {
|
|
460
|
+
return this.resetToLatest();
|
|
461
|
+
}
|
|
462
|
+
if (!result.length) {
|
|
463
|
+
const firstItem = this.getAt(0);
|
|
464
|
+
this.oldestId = firstItem ? this.getId(firstItem) : null;
|
|
465
|
+
await this.refreshFetchedState();
|
|
466
|
+
|
|
467
|
+
// LATEST state has priority over OLDEST
|
|
468
|
+
if (this.currentState === WindowState.PAST) {
|
|
469
|
+
this.currentState = WindowState.OLDEST;
|
|
470
|
+
}
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
this.addItems(result, 'head');
|
|
474
|
+
await this.refreshFetchedState();
|
|
475
|
+
}
|
|
476
|
+
async fetchNext() {
|
|
477
|
+
if (this.fetchingState || this.hasLatest) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
this.fetchingState = WindowState.PAST;
|
|
481
|
+
let result;
|
|
482
|
+
try {
|
|
483
|
+
result = await this.fetchItemsAfter();
|
|
484
|
+
} finally {
|
|
485
|
+
this.fetchingState = undefined;
|
|
486
|
+
}
|
|
487
|
+
if (!result) {
|
|
488
|
+
await this.resetToLatest();
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
if (result.length) {
|
|
492
|
+
this.addItems(result, 'tail');
|
|
493
|
+
await this.refreshFetchedState();
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
async refreshFetchedState() {
|
|
498
|
+
this.currentState = (await this.isLatestItemLoaded()) ? WindowState.LATEST : WindowState.PAST;
|
|
499
|
+
}
|
|
500
|
+
addItems(newItems, to) {
|
|
501
|
+
let result;
|
|
502
|
+
if (to === 'head') {
|
|
503
|
+
result = this.trimItemsArrayToLimit([...newItems, ...this.items], 'tail');
|
|
504
|
+
}
|
|
505
|
+
if (to === 'tail') {
|
|
506
|
+
result = this.trimItemsArrayToLimit([...this.items, ...newItems], 'head');
|
|
507
|
+
}
|
|
508
|
+
this.deleteAll();
|
|
509
|
+
this.set(...result);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Return array with messages of count that matching limit.
|
|
514
|
+
*/
|
|
515
|
+
trimItemsArrayToLimit(items, from) {
|
|
516
|
+
if (this.limit === null) {
|
|
517
|
+
return items;
|
|
518
|
+
}
|
|
519
|
+
if (from === 'head') {
|
|
520
|
+
return items.slice(-this.limit);
|
|
521
|
+
}
|
|
522
|
+
if (from === 'tail') {
|
|
523
|
+
return items.slice(0, this.limit);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
class TopicHistoryWindow extends TraversableRemoteCollection {
|
|
528
|
+
constructor(roomId, topicId, tracker) {
|
|
529
|
+
super('id');
|
|
530
|
+
this.roomId = roomId;
|
|
531
|
+
this.topicId = topicId;
|
|
532
|
+
this.tracker = tracker;
|
|
533
|
+
/**
|
|
534
|
+
* Reexported available window modes enum.
|
|
535
|
+
*/
|
|
536
|
+
TopicHistoryWindow_defineProperty(this, "WindowState", WindowState);
|
|
537
|
+
this.tracker.client.on('Session', ev => this.handleSession(ev));
|
|
538
|
+
this.tracker.client.on('NewMessage', ev => this.handleNewMessage(ev));
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* For internal use.
|
|
543
|
+
* @internal
|
|
544
|
+
*/
|
|
545
|
+
_updateMessageReference(refTopic) {
|
|
546
|
+
const refMessage = this.get(refTopic.refMessage.id);
|
|
547
|
+
if (refMessage) {
|
|
548
|
+
// Update referenced topic ID in message
|
|
549
|
+
this.set({
|
|
550
|
+
...refMessage,
|
|
551
|
+
topicRef: refTopic.id
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
async handleNewMessage(ev) {
|
|
556
|
+
if ([WindowState.LATEST, WindowState.LIVE].includes(this.state) && ev.message.location.roomId === this.roomId && ev.message.location.topicId === this.topicId) {
|
|
557
|
+
this.addItems([ev.message], 'tail');
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
handleSession(ev) {
|
|
561
|
+
const rooms = ev.state.rooms;
|
|
562
|
+
if (rooms.find(room => room.id === this.roomId)) {
|
|
563
|
+
this.resetToLatest();
|
|
564
|
+
} else {
|
|
565
|
+
this.deleteAll();
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
async fetchItemsAfter() {
|
|
569
|
+
const afterId = this.getAt(this.length - 1)?.id;
|
|
570
|
+
if (!afterId) {
|
|
571
|
+
// If there is no message to refer, fetch latest
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
const result = await this.tracker.client.send('GetMessages', {
|
|
575
|
+
location: {
|
|
576
|
+
roomId: this.roomId,
|
|
577
|
+
topicId: this.topicId
|
|
578
|
+
},
|
|
579
|
+
after: afterId
|
|
580
|
+
});
|
|
581
|
+
if (result.error) {
|
|
582
|
+
throw new Error(`Cannot fetch messages: ${result.error.message}`);
|
|
583
|
+
}
|
|
584
|
+
return result.data.messages;
|
|
585
|
+
}
|
|
586
|
+
async fetchItemsBefore() {
|
|
587
|
+
const beforeId = this.getAt(0)?.id;
|
|
588
|
+
if (!beforeId) {
|
|
589
|
+
// If there is no message to refer, fetch latest
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
const result = await this.tracker.client.send('GetMessages', {
|
|
593
|
+
location: {
|
|
594
|
+
roomId: this.roomId,
|
|
595
|
+
topicId: this.topicId
|
|
596
|
+
},
|
|
597
|
+
before: beforeId
|
|
598
|
+
});
|
|
599
|
+
if (result.error) {
|
|
600
|
+
throw new Error(`Cannot fetch messages: ${result.error.message}`);
|
|
601
|
+
}
|
|
602
|
+
return result.data.messages;
|
|
603
|
+
}
|
|
604
|
+
async fetchLatestItems() {
|
|
605
|
+
const result = await this.tracker.client.send('GetMessages', {
|
|
606
|
+
location: {
|
|
607
|
+
roomId: this.roomId,
|
|
608
|
+
topicId: this.topicId
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
if (result.error) {
|
|
612
|
+
throw new Error(`Cannot fetch messages: ${result.error.message}`);
|
|
613
|
+
}
|
|
614
|
+
return result.data.messages;
|
|
615
|
+
}
|
|
616
|
+
async getTopic() {
|
|
617
|
+
return (await this.tracker.rooms.getTopics(this.roomId, [this.topicId])).get(this.topicId);
|
|
618
|
+
}
|
|
619
|
+
async getLatestMessageId() {
|
|
620
|
+
return (await this.getTopic())?.lastMessage?.id;
|
|
621
|
+
}
|
|
622
|
+
async isLatestItemLoaded() {
|
|
623
|
+
const lastMessageId = await this.getLatestMessageId();
|
|
624
|
+
return lastMessageId ? this.has(lastMessageId) : true;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
;// CONCATENATED MODULE: ./src/state-tracker/RoomMessagesHistory.ts
|
|
628
|
+
function RoomMessagesHistory_defineProperty(obj, key, value) { key = RoomMessagesHistory_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
629
|
+
function RoomMessagesHistory_toPropertyKey(arg) { var key = RoomMessagesHistory_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
630
|
+
function RoomMessagesHistory_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
class RoomMessagesHistory {
|
|
634
|
+
constructor(room, tracker) {
|
|
635
|
+
this.room = room;
|
|
636
|
+
this.tracker = tracker;
|
|
637
|
+
RoomMessagesHistory_defineProperty(this, "historyWindows", new IndexedCollection());
|
|
638
|
+
this.tracker.client.on('RoomUpdated', ev => this.handleRoomUpdated(ev));
|
|
639
|
+
this.tracker.client.on('NewTopic', ev => this.handleNewTopic(ev));
|
|
640
|
+
this.tracker.client.on('TopicDeleted', ev => this.handleTopicDeleted(ev));
|
|
641
|
+
if (this.room.defaultTopic) {
|
|
642
|
+
this.createHistoryWindowForTopic(this.room.defaultTopic);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Returns a history window object for the given topic ID, allowing you to view message history.
|
|
648
|
+
*/
|
|
649
|
+
async getMessagesWindow(topicId) {
|
|
650
|
+
let historyWindow = this.historyWindows.get(topicId);
|
|
651
|
+
if (!historyWindow) {
|
|
652
|
+
const topic = (await this.tracker.rooms.getTopics(this.room.id, [topicId])).get(topicId);
|
|
653
|
+
if (topic) {
|
|
654
|
+
this.createHistoryWindowForTopic(topic);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return this.historyWindows.get(topicId);
|
|
658
|
+
}
|
|
659
|
+
handleRoomUpdated(ev) {
|
|
660
|
+
if (this.room.id === ev.room.id) {
|
|
661
|
+
this.room = ev.room;
|
|
662
|
+
if (ev.room.defaultTopic) {
|
|
663
|
+
this.createHistoryWindowForTopic(ev.room.defaultTopic);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
handleNewTopic(ev) {
|
|
668
|
+
if (this.room.id === ev.roomId) {
|
|
669
|
+
this.createHistoryWindowForTopic(ev.topic);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
handleTopicDeleted(ev) {
|
|
673
|
+
if (this.room.id === ev.location.roomId) {
|
|
674
|
+
this.historyWindows.delete(ev.location.topicId);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
createHistoryWindowForTopic(topic) {
|
|
678
|
+
if (this.historyWindows.has(topic.id)) {
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
this.historyWindows.set([topic.id, new TopicHistoryWindow(this.room.id, topic.id, this.tracker)]);
|
|
682
|
+
|
|
683
|
+
// If new topic refers to some message from this room, update other structures
|
|
684
|
+
if (topic.refMessage) {
|
|
685
|
+
const refHistoryWindow = this.historyWindows.get(topic.refMessage.location.topicId);
|
|
686
|
+
refHistoryWindow?._updateMessageReference(topic);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
;// CONCATENATED MODULE: ./src/state-tracker/MessagesManager.ts
|
|
691
|
+
function MessagesManager_defineProperty(obj, key, value) { key = MessagesManager_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
692
|
+
function MessagesManager_toPropertyKey(arg) { var key = MessagesManager_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
693
|
+
function MessagesManager_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
class MessagesManager {
|
|
698
|
+
constructor(tracker) {
|
|
699
|
+
this.tracker = tracker;
|
|
700
|
+
MessagesManager_defineProperty(this, "roomHistories", new IndexedCollection());
|
|
701
|
+
MessagesManager_defineProperty(this, "followedTopics", new IndexedCollection());
|
|
702
|
+
MessagesManager_defineProperty(this, "followedTopicsPromises", new PromiseRegistry());
|
|
703
|
+
MessagesManager_defineProperty(this, "deferredSession", new DeferredTask());
|
|
704
|
+
this.tracker.client.on('Session', ev => this.handleSession(ev));
|
|
705
|
+
this.tracker.client.on('RoomJoined', ev => this.handleRoomJoin(ev));
|
|
706
|
+
this.tracker.client.on('NewTopic', ev => this.handleNewTopic(ev));
|
|
707
|
+
this.tracker.client.on('FollowedTopicUpdated', ev => this.handleFollowedTopicUpdated(ev));
|
|
708
|
+
this.tracker.client.on('TopicFollowed', ev => this.handleTopicFollowed(ev));
|
|
709
|
+
this.tracker.client.on('TopicUnfollowed', ev => this.handleTopicUnfollowed(ev));
|
|
710
|
+
this.tracker.client.on('NewMessage', ev => this.handleNewMessage(ev));
|
|
711
|
+
this.tracker.client.on('RoomDeleted', ev => this.handleRoomDeleted(ev));
|
|
712
|
+
this.tracker.client.on('RoomLeft', ev => this.handleRoomLeft(ev));
|
|
713
|
+
this.tracker.client.on('TopicDeleted', ev => this.handleTopicDeleted(ev));
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Get history manager for given room ID.
|
|
718
|
+
*/
|
|
719
|
+
async getRoomHistory(roomId) {
|
|
720
|
+
await this.deferredSession.promise;
|
|
721
|
+
return this.roomHistories.get(roomId);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Cache followed topics for all joined rooms in a space and fetch them in bulk if necessary.
|
|
726
|
+
* Then you can get them using getRoomFollowedTopics().
|
|
727
|
+
* @see getRoomFollowedTopics
|
|
728
|
+
*/
|
|
729
|
+
async cacheSpaceFollowedTopics(spaceId) {
|
|
730
|
+
if (spaceId && !(await this.tracker.spaces.get()).has(spaceId)) {
|
|
731
|
+
throw new Error(`You are not in space ${spaceId}`);
|
|
732
|
+
}
|
|
733
|
+
const roomIds = (await this.tracker.rooms.get()).findBy('spaceId', spaceId).items.map(room => room.id);
|
|
734
|
+
if (!roomIds.length) {
|
|
735
|
+
// We don't need to ping server for followed topics for this space, if user has no joined rooms
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
const resultPromise = this.tracker.client.send('GetFollowedTopics', {
|
|
739
|
+
location: {
|
|
740
|
+
spaceId
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
roomIds.forEach(roomId => this.followedTopicsPromises.register(resultPromise, roomId));
|
|
744
|
+
const result = await resultPromise;
|
|
745
|
+
if (result.error) {
|
|
746
|
+
throw result.error;
|
|
747
|
+
}
|
|
748
|
+
this.setFollowedTopicsArray(roomIds, result.data.followedTopics);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Get followed topics for the given room.
|
|
753
|
+
* @return Undefined if you are not in the room, collection otherwise.
|
|
754
|
+
*/
|
|
755
|
+
async getRoomFollowedTopics(roomId) {
|
|
756
|
+
if (!(await this.tracker.rooms.get()).has(roomId)) {
|
|
757
|
+
return undefined;
|
|
758
|
+
}
|
|
759
|
+
if (!this.followedTopics.has(roomId)) {
|
|
760
|
+
if (this.followedTopicsPromises.notExist(roomId)) {
|
|
761
|
+
this.followedTopicsPromises.registerByFunction(async () => {
|
|
762
|
+
const result = await this.tracker.client.send('GetFollowedTopics', {
|
|
763
|
+
location: {
|
|
764
|
+
roomId
|
|
765
|
+
}
|
|
766
|
+
});
|
|
767
|
+
if (result.error) {
|
|
768
|
+
throw result.error;
|
|
769
|
+
}
|
|
770
|
+
this.setFollowedTopicsArray([roomId], result.data.followedTopics);
|
|
771
|
+
}, roomId);
|
|
772
|
+
}
|
|
773
|
+
await this.followedTopicsPromises.get(roomId);
|
|
774
|
+
}
|
|
775
|
+
return this.followedTopics.get(roomId);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Batch acknowledge all missed messages from any topics in given room.
|
|
780
|
+
*/
|
|
781
|
+
async ackRoomFollowedTopics(roomId) {
|
|
782
|
+
const collection = await this.getRoomFollowedTopics(roomId);
|
|
783
|
+
if (!collection) {
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
for (const followedTopic of collection.items) {
|
|
787
|
+
if (followedTopic.missed) {
|
|
788
|
+
await this.tracker.client.send('Ack', {
|
|
789
|
+
location: followedTopic.location
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Calculate missed messages from any topic in given room.
|
|
797
|
+
* @return Undefined if you are not in room.
|
|
798
|
+
*/
|
|
799
|
+
async calculateRoomMissedMessages(roomId) {
|
|
800
|
+
const collection = await this.getRoomFollowedTopics(roomId);
|
|
801
|
+
if (collection) {
|
|
802
|
+
return collection.items.reduce((previousValue, currentValue) => previousValue + (currentValue.missed ?? 0), 0);
|
|
803
|
+
}
|
|
804
|
+
return undefined;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* For internal use. If you want to delete the message, execute a proper command on client object.
|
|
809
|
+
* @internal
|
|
810
|
+
*/
|
|
811
|
+
_deleteByTopicIds(roomId, ...topicIds) {
|
|
812
|
+
this.followedTopics.get(roomId)?.delete(...topicIds);
|
|
813
|
+
}
|
|
814
|
+
createHistoryForNewRoom(room) {
|
|
815
|
+
this.roomHistories.set([room.id, new RoomMessagesHistory(room, this.tracker)]);
|
|
816
|
+
}
|
|
817
|
+
handleNewMessage(ev) {
|
|
818
|
+
this.updateLocallyFollowedTopicOnNewMessage(ev);
|
|
819
|
+
}
|
|
820
|
+
handleFollowedTopicUpdated(ev) {
|
|
821
|
+
this.followedTopics.get(ev.followedTopic.location.roomId)?.set(ev.followedTopic);
|
|
822
|
+
}
|
|
823
|
+
handleTopicFollowed(ev) {
|
|
824
|
+
this.setFollowedTopicsArray([ev.followedTopic.location.roomId], [ev.followedTopic]);
|
|
825
|
+
}
|
|
826
|
+
handleTopicUnfollowed(ev) {
|
|
827
|
+
this.followedTopics.get(ev.location.roomId)?.delete(ev.location.topicId);
|
|
828
|
+
}
|
|
829
|
+
handleRoomDeleted(ev) {
|
|
830
|
+
this.roomHistories.delete(ev.id);
|
|
831
|
+
this.clearRoomFollowedTopicsStructures(ev.id);
|
|
832
|
+
}
|
|
833
|
+
handleRoomJoin(ev) {
|
|
834
|
+
this.createHistoryForNewRoom(ev.room);
|
|
835
|
+
this.clearRoomFollowedTopicsStructures(ev.room.id);
|
|
836
|
+
}
|
|
837
|
+
handleRoomLeft(ev) {
|
|
838
|
+
this.roomHistories.delete(ev.id);
|
|
839
|
+
this.clearRoomFollowedTopicsStructures(ev.id);
|
|
840
|
+
}
|
|
841
|
+
async handleNewTopic(ev) {
|
|
842
|
+
if (this.followedTopics.has(ev.roomId)) {
|
|
843
|
+
// Check if the new topic is followed by user
|
|
844
|
+
// only if client asked for followed topics list before for this room
|
|
845
|
+
const result = await this.tracker.client.send('GetFollowedTopics', {
|
|
846
|
+
location: {
|
|
847
|
+
roomId: ev.roomId,
|
|
848
|
+
topicId: ev.topic.id
|
|
849
|
+
}
|
|
850
|
+
});
|
|
851
|
+
const followedTopic = result.data.followedTopics[0];
|
|
852
|
+
if (followedTopic) {
|
|
853
|
+
this.followedTopics.get(ev.roomId).set(followedTopic);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
handleTopicDeleted(ev) {
|
|
858
|
+
this.followedTopics.get(ev.location.roomId)?.delete(ev.location.topicId);
|
|
859
|
+
}
|
|
860
|
+
handleSession(ev) {
|
|
861
|
+
this.followedTopics.deleteAll();
|
|
862
|
+
this.followedTopicsPromises.forgetAll();
|
|
863
|
+
this.roomHistories.deleteAll();
|
|
864
|
+
ev.state.rooms.forEach(room => this.createHistoryForNewRoom(room));
|
|
865
|
+
this.deferredSession.resolve();
|
|
866
|
+
}
|
|
867
|
+
updateLocallyFollowedTopicOnNewMessage(ev) {
|
|
868
|
+
const roomFollowedTopics = this.followedTopics.get(ev.message.location.roomId);
|
|
869
|
+
const followedTopic = roomFollowedTopics?.get(ev.message.location.topicId);
|
|
870
|
+
if (!roomFollowedTopics || !followedTopic) {
|
|
871
|
+
// Skip if we don't follow this room or targeted topic
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
const isMe = ev.message.author.user.id === this.tracker.me?.id;
|
|
875
|
+
let update;
|
|
876
|
+
if (isMe) {
|
|
877
|
+
// Reset missed messages count if new message is authored by me
|
|
878
|
+
update = {
|
|
879
|
+
missed: 0,
|
|
880
|
+
lastAckMessageId: ev.message.id
|
|
881
|
+
};
|
|
882
|
+
} else {
|
|
883
|
+
// ...add 1 otherwise
|
|
884
|
+
update = {
|
|
885
|
+
missed: followedTopic.missed === null ? null : followedTopic.missed + 1
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
roomFollowedTopics.set({
|
|
889
|
+
...followedTopic,
|
|
890
|
+
...update
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
setFollowedTopicsArray(roomIds, followedTopics) {
|
|
894
|
+
const roomToTopics = {};
|
|
895
|
+
|
|
896
|
+
// Reassign followed topics to limit collection change event emit
|
|
897
|
+
followedTopics.forEach(followedTopic => {
|
|
898
|
+
roomToTopics[followedTopic.location.roomId] ??= [];
|
|
899
|
+
roomToTopics[followedTopic.location.roomId].push(followedTopic);
|
|
900
|
+
});
|
|
901
|
+
roomIds.forEach(roomId => {
|
|
902
|
+
if (!this.followedTopics.has(roomId)) {
|
|
903
|
+
this.followedTopics.set([roomId, new ObservableIndexedObjectCollection(followedTopic => followedTopic.location.topicId)]);
|
|
904
|
+
}
|
|
905
|
+
if (roomToTopics[roomId]) {
|
|
906
|
+
this.followedTopics.get(roomId).set(...roomToTopics[roomId]);
|
|
907
|
+
}
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
clearRoomFollowedTopicsStructures(roomId) {
|
|
911
|
+
this.followedTopics.delete(roomId);
|
|
912
|
+
this.followedTopicsPromises.forget(roomId);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
;// CONCATENATED MODULE: ./src/state-tracker/RoomsManager.ts
|
|
916
|
+
function RoomsManager_defineProperty(obj, key, value) { key = RoomsManager_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
917
|
+
function RoomsManager_toPropertyKey(arg) { var key = RoomsManager_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
918
|
+
function RoomsManager_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
class RoomsManager {
|
|
923
|
+
constructor(tracker) {
|
|
924
|
+
this.tracker = tracker;
|
|
925
|
+
RoomsManager_defineProperty(this, "messages", void 0);
|
|
926
|
+
RoomsManager_defineProperty(this, "list", new ObservableIndexedObjectCollection('id'));
|
|
927
|
+
RoomsManager_defineProperty(this, "topics", new IndexedCollection());
|
|
928
|
+
RoomsManager_defineProperty(this, "members", new IndexedCollection());
|
|
929
|
+
RoomsManager_defineProperty(this, "deferredSession", new DeferredTask());
|
|
930
|
+
RoomsManager_defineProperty(this, "membersPromises", new PromiseRegistry());
|
|
931
|
+
RoomsManager_defineProperty(this, "topicsPromises", new PromiseRegistry());
|
|
932
|
+
this.messages = new MessagesManager(tracker);
|
|
933
|
+
this.tracker.client.on('NewMessage', ev => this.handleNewMessage(ev));
|
|
934
|
+
this.tracker.client.on('NewTopic', ev => this.handleNewTopic(ev));
|
|
935
|
+
this.tracker.client.on('TopicDeleted', ev => this.handleTopicDeleted(ev));
|
|
936
|
+
this.tracker.client.on('RoomJoined', ev => this.handleRoomJoined(ev));
|
|
937
|
+
this.tracker.client.on('RoomLeft', ev => this.handleRoomLeft(ev));
|
|
938
|
+
this.tracker.client.on('RoomUpdated', ev => this.handleRoomUpdated(ev));
|
|
939
|
+
this.tracker.client.on('RoomDeleted', ev => this.handleRoomDeleted(ev));
|
|
940
|
+
this.tracker.client.on('TopicUpdated', ev => this.handleTopicUpdated(ev));
|
|
941
|
+
this.tracker.client.on('RoomMemberJoined', ev => this.handleRoomMemberJoined(ev));
|
|
942
|
+
this.tracker.client.on('RoomMemberLeft', ev => this.handleRoomMemberLeft(ev));
|
|
943
|
+
this.tracker.client.on('RoomMembers', ev => this.handleRoomMembers(ev));
|
|
944
|
+
this.tracker.client.on('RoomMemberUpdated', ev => this.handleRoomMemberUpdated(ev));
|
|
945
|
+
this.tracker.client.on('SpaceMemberLeft', ev => this.handleSpaceMemberLeft(ev));
|
|
946
|
+
this.tracker.client.on('SpaceMemberUpdated', ev => this.handleSpaceMemberUpdated(ev));
|
|
947
|
+
this.tracker.client.on('SpaceDeleted', ev => this.handleSpaceDeleted(ev));
|
|
948
|
+
this.tracker.client.on('SpaceLeft', ev => this.handleSpaceDeleted(ev));
|
|
949
|
+
this.tracker.client.on('UserUpdated', ev => this.handleUserUpdated(ev));
|
|
950
|
+
this.tracker.client.on('Session', ev => this.handleSession(ev));
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Get collection of room members.
|
|
955
|
+
*/
|
|
956
|
+
async getMembers(roomId) {
|
|
957
|
+
if (this.membersPromises.notExist(roomId)) {
|
|
958
|
+
this.membersPromises.registerByFunction(async () => {
|
|
959
|
+
const result = await this.tracker.client.send('GetRoomMembers', {
|
|
960
|
+
id: roomId
|
|
961
|
+
});
|
|
962
|
+
if (result.error) {
|
|
963
|
+
throw result.error;
|
|
964
|
+
}
|
|
965
|
+
this.handleRoomMembers(result.data);
|
|
966
|
+
}, roomId);
|
|
967
|
+
}
|
|
968
|
+
await this.membersPromises.get(roomId);
|
|
969
|
+
return this.members.get(roomId);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* Get a room member representing the current user.
|
|
974
|
+
*/
|
|
975
|
+
async getMe(roomId) {
|
|
976
|
+
const userId = (await this.tracker.getMe()).id;
|
|
977
|
+
if (!this.list.has(roomId)) {
|
|
978
|
+
// User is not in passed room.
|
|
979
|
+
return undefined;
|
|
980
|
+
}
|
|
981
|
+
const members = await this.getMembers(roomId);
|
|
982
|
+
return members?.items.find(member => (member.user?.id ?? member.spaceMember.user.id) === userId);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* Get collection of all the rooms you are in.
|
|
987
|
+
*/
|
|
988
|
+
async get() {
|
|
989
|
+
await this.deferredSession.promise;
|
|
990
|
+
return this.list;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
/**
|
|
994
|
+
* Get a collection of locally cached Topic objects for given room.
|
|
995
|
+
* You can pass topic ids as second argument, to try to fetch them from the server.
|
|
996
|
+
*/
|
|
997
|
+
async getTopics(roomId, tryToFetchTopicIds) {
|
|
998
|
+
await this.deferredSession.promise;
|
|
999
|
+
if (tryToFetchTopicIds?.length) {
|
|
1000
|
+
// Topic can be fetched if it isn't already cached and fetch is not already in progress
|
|
1001
|
+
const canFetch = topicId => !this.topics.get(roomId)?.has(topicId) && !this.topicsPromises.has(roomId + topicId);
|
|
1002
|
+
const idsToFetch = tryToFetchTopicIds.filter(canFetch);
|
|
1003
|
+
if (idsToFetch.length) {
|
|
1004
|
+
const promise = this.tracker.client.send('GetTopics', {
|
|
1005
|
+
roomId,
|
|
1006
|
+
topicIds: idsToFetch
|
|
1007
|
+
}).then(result => this.topics.get(result.data.location.roomId)?.set(...result.data.topics));
|
|
1008
|
+
idsToFetch.forEach(topicId => this.topicsPromises.register(promise, roomId + topicId));
|
|
1009
|
+
}
|
|
1010
|
+
for (const topicId of tryToFetchTopicIds) {
|
|
1011
|
+
await this.topicsPromises.get(roomId + topicId);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return this.topics.get(roomId);
|
|
1015
|
+
}
|
|
1016
|
+
deleteRoom(...roomIds) {
|
|
1017
|
+
this.list.delete(...roomIds);
|
|
1018
|
+
this.members.delete(...roomIds);
|
|
1019
|
+
this.membersPromises.forget(...roomIds);
|
|
1020
|
+
for (const roomId of roomIds) {
|
|
1021
|
+
const topicIds = this.topics.get(roomId)?.items.map(topic => topic.id) ?? [];
|
|
1022
|
+
this.messages._deleteByTopicIds(roomId, ...topicIds);
|
|
1023
|
+
}
|
|
1024
|
+
this.topics.delete(...roomIds);
|
|
1025
|
+
}
|
|
1026
|
+
deleteRoomsBySpaceId(spaceId) {
|
|
1027
|
+
this.deleteRoom(...this.list.findBy('spaceId', spaceId).items.map(room => room.id));
|
|
1028
|
+
}
|
|
1029
|
+
handleSpaceMemberUpdated(ev) {
|
|
1030
|
+
// Update members of rooms related to this space
|
|
1031
|
+
for (const room of this.list.findBy('spaceId', ev.spaceId).items) {
|
|
1032
|
+
const roomMembers = this.members.get(room.id);
|
|
1033
|
+
if (!roomMembers || !roomMembers.has(ev.userId)) {
|
|
1034
|
+
// Skip update if member list for this room is not loaded
|
|
1035
|
+
// or user is not in room
|
|
1036
|
+
continue;
|
|
1037
|
+
}
|
|
1038
|
+
const roomMember = roomMembers.get(ev.userId);
|
|
1039
|
+
const user = roomMember.spaceMember.user;
|
|
1040
|
+
|
|
1041
|
+
// Update space member but first fill user object (it's null in event object)
|
|
1042
|
+
roomMember.spaceMember = {
|
|
1043
|
+
...ev.member,
|
|
1044
|
+
user
|
|
1045
|
+
};
|
|
1046
|
+
roomMembers.set(roomMember);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
handleSpaceMemberLeft(ev) {
|
|
1050
|
+
this.list.findBy('spaceId', ev.spaceId).items.forEach(room => this.members.get(room.id)?.delete(ev.userId));
|
|
1051
|
+
}
|
|
1052
|
+
handleRoomMemberUpdated(ev) {
|
|
1053
|
+
if (!this.members.has(ev.roomId)) {
|
|
1054
|
+
// We do not track member list for this room.
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
const members = this.members.get(ev.roomId);
|
|
1058
|
+
const member = members.get(ev.userId);
|
|
1059
|
+
const newMember = ev.member;
|
|
1060
|
+
const user = member.spaceMember?.user ?? member.user;
|
|
1061
|
+
if (newMember.spaceMember) {
|
|
1062
|
+
newMember.spaceMember.user = user;
|
|
1063
|
+
} else {
|
|
1064
|
+
newMember.user = user;
|
|
1065
|
+
}
|
|
1066
|
+
members.set(newMember);
|
|
1067
|
+
}
|
|
1068
|
+
handleSpaceDeleted(ev) {
|
|
1069
|
+
this.deleteRoomsBySpaceId(ev.id);
|
|
1070
|
+
}
|
|
1071
|
+
handleTopicDeleted(ev) {
|
|
1072
|
+
const collection = this.topics.get(ev.location.roomId);
|
|
1073
|
+
collection.delete(ev.location.topicId);
|
|
1074
|
+
const room = this.list.get(ev.location.roomId);
|
|
1075
|
+
if (room.defaultTopic?.id === ev.location.topicId) {
|
|
1076
|
+
this.list.set({
|
|
1077
|
+
...room,
|
|
1078
|
+
defaultTopic: null
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
handleNewTopic(ev) {
|
|
1083
|
+
this.addJoinedRoomTopics(ev.roomId, ev.topic);
|
|
1084
|
+
}
|
|
1085
|
+
addJoinedRoomTopics(roomId, ...topics) {
|
|
1086
|
+
if (this.topics.has(roomId)) {
|
|
1087
|
+
this.topics.get(roomId).set(...topics);
|
|
1088
|
+
} else {
|
|
1089
|
+
this.topics.set([roomId, new ObservableIndexedObjectCollection('id', topics)]);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
handleRoomJoined(ev) {
|
|
1093
|
+
this.addJoinedRooms(ev.room);
|
|
1094
|
+
}
|
|
1095
|
+
handleRoomUpdated(ev) {
|
|
1096
|
+
this.list.set(ev.room);
|
|
1097
|
+
}
|
|
1098
|
+
handleRoomDeleted(ev) {
|
|
1099
|
+
this.deleteRoom(ev.id);
|
|
1100
|
+
}
|
|
1101
|
+
handleTopicUpdated(ev) {
|
|
1102
|
+
const room = this.list.get(ev.location.roomId);
|
|
1103
|
+
if (this.topics.get(ev.location.roomId)?.has(ev.topic.id)) {
|
|
1104
|
+
this.topics.get(ev.location.roomId).set(ev.topic);
|
|
1105
|
+
}
|
|
1106
|
+
if (room.defaultTopic.id === ev.topic.id) {
|
|
1107
|
+
room.defaultTopic = ev.topic;
|
|
1108
|
+
this.list.set(room);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
addJoinedRooms(...rooms) {
|
|
1112
|
+
for (const room of rooms) {
|
|
1113
|
+
if (room.defaultTopic) {
|
|
1114
|
+
this.addJoinedRoomTopics(room.id, room.defaultTopic);
|
|
1115
|
+
}
|
|
1116
|
+
if (room.type === 'Pm' && room.recipients) {
|
|
1117
|
+
// Treat PM recipients as normal room members.
|
|
1118
|
+
// We are registering fake promise in `memberPromises`
|
|
1119
|
+
// because GetMembers are not supported for PM rooms.
|
|
1120
|
+
this.handleRoomMembers({
|
|
1121
|
+
id: room.id,
|
|
1122
|
+
members: room.recipients.map(user => ({
|
|
1123
|
+
user,
|
|
1124
|
+
spaceMember: null,
|
|
1125
|
+
roles: null
|
|
1126
|
+
}))
|
|
1127
|
+
});
|
|
1128
|
+
this.membersPromises.register(Promise.resolve(), room.id);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
this.list.set(...rooms);
|
|
1132
|
+
}
|
|
1133
|
+
handleRoomLeft(ev) {
|
|
1134
|
+
this.deleteRoom(ev.id);
|
|
1135
|
+
}
|
|
1136
|
+
handleRoomMemberJoined(ev) {
|
|
1137
|
+
if (this.members.has(ev.roomId)) {
|
|
1138
|
+
this.members.get(ev.roomId).set(ev.member);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
handleRoomMemberLeft(ev) {
|
|
1142
|
+
if (this.members.has(ev.roomId)) {
|
|
1143
|
+
this.members.get(ev.roomId).delete(ev.userId);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
handleRoomMembers(ev) {
|
|
1147
|
+
if (!this.members.has(ev.id)) {
|
|
1148
|
+
this.members.set([ev.id, new ObservableIndexedObjectCollection(member => member.user?.id ?? member.spaceMember.user.id, ev.members)]);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
handleSession(ev) {
|
|
1152
|
+
this.list.deleteAll();
|
|
1153
|
+
this.topics.deleteAll();
|
|
1154
|
+
this.topicsPromises.forgetAll();
|
|
1155
|
+
this.members.deleteAll();
|
|
1156
|
+
this.membersPromises.forgetAll();
|
|
1157
|
+
this.addJoinedRooms(...ev.state.rooms);
|
|
1158
|
+
this.deferredSession.resolve();
|
|
1159
|
+
}
|
|
1160
|
+
handleUserUpdated(ev) {
|
|
1161
|
+
this.members.items.forEach(members => {
|
|
1162
|
+
const member = members.get(ev.user.id);
|
|
1163
|
+
if (!member) {
|
|
1164
|
+
// Skip room; updated user is not here
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
const newMember = {
|
|
1168
|
+
...member
|
|
1169
|
+
};
|
|
1170
|
+
if (member.user) {
|
|
1171
|
+
newMember.user = ev.user;
|
|
1172
|
+
} else {
|
|
1173
|
+
newMember.spaceMember.user = ev.user;
|
|
1174
|
+
}
|
|
1175
|
+
members.set(newMember);
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
handleNewMessage(ev) {
|
|
1179
|
+
const topics = this.topics.get(ev.message.location.roomId);
|
|
1180
|
+
const topic = topics?.get(ev.message.location.topicId);
|
|
1181
|
+
if (topic) {
|
|
1182
|
+
topics.set({
|
|
1183
|
+
...topic,
|
|
1184
|
+
messageCount: topic.messageCount + 1,
|
|
1185
|
+
lastMessage: ev.message
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
;// CONCATENATED MODULE: ./src/state-tracker/functions.ts
|
|
1191
|
+
function reorderRolesOnPriorityUpdate(allRoles, oldRole, updatedRole) {
|
|
1192
|
+
// If the priority has changed, adjust the rest of roles
|
|
1193
|
+
const increased = updatedRole.priority - oldRole.priority > 0;
|
|
1194
|
+
const decreased = !increased;
|
|
1195
|
+
const changedRoles = [];
|
|
1196
|
+
allRoles.forEach(role => {
|
|
1197
|
+
if (role.id === updatedRole.id) {
|
|
1198
|
+
// Skip the updated role
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
if (increased && oldRole.priority <= role.priority) {
|
|
1202
|
+
role.priority--;
|
|
1203
|
+
changedRoles.push(role);
|
|
1204
|
+
}
|
|
1205
|
+
if (decreased && updatedRole.priority <= role.priority) {
|
|
1206
|
+
role.priority++;
|
|
1207
|
+
changedRoles.push(role);
|
|
1208
|
+
}
|
|
1209
|
+
});
|
|
1210
|
+
return changedRoles;
|
|
1211
|
+
}
|
|
1212
|
+
function extractUserFromMember(member) {
|
|
1213
|
+
return member.user ?? member.spaceMember?.user;
|
|
1214
|
+
}
|
|
1215
|
+
;// CONCATENATED MODULE: ./src/state-tracker/SpacesManager.ts
|
|
1216
|
+
function SpacesManager_defineProperty(obj, key, value) { key = SpacesManager_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
1217
|
+
function SpacesManager_toPropertyKey(arg) { var key = SpacesManager_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
1218
|
+
function SpacesManager_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
class SpacesManager {
|
|
1223
|
+
constructor(tracker) {
|
|
1224
|
+
this.tracker = tracker;
|
|
1225
|
+
SpacesManager_defineProperty(this, "list", new ObservableIndexedObjectCollection('id'));
|
|
1226
|
+
SpacesManager_defineProperty(this, "roles", new IndexedCollection());
|
|
1227
|
+
SpacesManager_defineProperty(this, "rooms", new IndexedCollection());
|
|
1228
|
+
SpacesManager_defineProperty(this, "roomIdToSpaceId", new IndexedCollection());
|
|
1229
|
+
SpacesManager_defineProperty(this, "members", new IndexedCollection());
|
|
1230
|
+
SpacesManager_defineProperty(this, "deferredSession", new DeferredTask());
|
|
1231
|
+
SpacesManager_defineProperty(this, "roomsPromises", new PromiseRegistry());
|
|
1232
|
+
SpacesManager_defineProperty(this, "membersPromises", new PromiseRegistry());
|
|
1233
|
+
this.tracker.client.on('NewRoom', ev => this.handleNewRoom(ev));
|
|
1234
|
+
this.tracker.client.on('RoomDeleted', ev => this.handleRoomDeleted(ev));
|
|
1235
|
+
this.tracker.client.on('RoomUpdated', ev => this.handleRoomUpdated(ev));
|
|
1236
|
+
this.tracker.client.on('SpaceDeleted', ev => this.handleSpaceDeleted(ev));
|
|
1237
|
+
this.tracker.client.on('SpaceUpdated', ev => this.handleSpaceUpdated(ev));
|
|
1238
|
+
this.tracker.client.on('SpaceJoined', ev => this.handleSpaceJoined(ev));
|
|
1239
|
+
this.tracker.client.on('SpaceLeft', ev => this.handleSpaceDeleted(ev));
|
|
1240
|
+
this.tracker.client.on('SpaceMemberJoined', ev => this.handleSpaceMemberJoined(ev));
|
|
1241
|
+
this.tracker.client.on('SpaceMemberLeft', ev => this.handleSpaceMemberLeft(ev));
|
|
1242
|
+
this.tracker.client.on('SpaceMembers', ev => this.handleSpaceMembers(ev));
|
|
1243
|
+
this.tracker.client.on('SpaceRooms', ev => this.handleSpaceRooms(ev));
|
|
1244
|
+
this.tracker.client.on('SpaceMemberUpdated', ev => this.handleSpaceMemberUpdated(ev));
|
|
1245
|
+
this.tracker.client.on('UserUpdated', ev => this.handleUserUpdated(ev));
|
|
1246
|
+
this.tracker.client.on('NewRole', ev => this.handleNewRole(ev));
|
|
1247
|
+
this.tracker.client.on('RoleDeleted', ev => this.handleRoleDeleted(ev));
|
|
1248
|
+
this.tracker.client.on('RoleUpdated', ev => this.handleRoleUpdated(ev));
|
|
1249
|
+
this.tracker.client.on('Session', ev => this.handleSession(ev));
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
/**
|
|
1253
|
+
* Get collection of all the spaces you are in.
|
|
1254
|
+
*/
|
|
1255
|
+
async get() {
|
|
1256
|
+
await this.deferredSession.promise;
|
|
1257
|
+
return this.list;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* Get collection of space roles.
|
|
1262
|
+
*/
|
|
1263
|
+
async getRoles(spaceId) {
|
|
1264
|
+
await this.deferredSession.promise;
|
|
1265
|
+
return this.roles.get(spaceId);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
/**
|
|
1269
|
+
* Get collection of the all available rooms inside given space.
|
|
1270
|
+
*/
|
|
1271
|
+
async getRooms(spaceId) {
|
|
1272
|
+
if (this.roomsPromises.notExist(spaceId)) {
|
|
1273
|
+
this.roomsPromises.registerByFunction(async () => {
|
|
1274
|
+
const result = await this.tracker.client.send('GetSpaceRooms', {
|
|
1275
|
+
id: spaceId
|
|
1276
|
+
});
|
|
1277
|
+
if (result.error) {
|
|
1278
|
+
throw result.error;
|
|
1279
|
+
}
|
|
1280
|
+
this.handleSpaceRooms(result.data);
|
|
1281
|
+
}, spaceId);
|
|
1282
|
+
}
|
|
1283
|
+
await this.roomsPromises.get(spaceId);
|
|
1284
|
+
return this.rooms.get(spaceId);
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
/**
|
|
1288
|
+
* Get collection of space members.
|
|
1289
|
+
*/
|
|
1290
|
+
async getMembers(spaceId) {
|
|
1291
|
+
if (this.membersPromises.notExist(spaceId)) {
|
|
1292
|
+
this.membersPromises.registerByFunction(async () => {
|
|
1293
|
+
const result = await this.tracker.client.send('GetSpaceMembers', {
|
|
1294
|
+
id: spaceId
|
|
1295
|
+
});
|
|
1296
|
+
if (result.error) {
|
|
1297
|
+
throw result.error;
|
|
1298
|
+
}
|
|
1299
|
+
this.handleSpaceMembers(result.data);
|
|
1300
|
+
}, spaceId);
|
|
1301
|
+
}
|
|
1302
|
+
await this.membersPromises.get(spaceId);
|
|
1303
|
+
return this.members.get(spaceId);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
/**
|
|
1307
|
+
* Get a space member representing the current user.
|
|
1308
|
+
*/
|
|
1309
|
+
async getMe(spaceId) {
|
|
1310
|
+
const userId = (await this.tracker.getMe()).id;
|
|
1311
|
+
if (!this.list.has(spaceId)) {
|
|
1312
|
+
// User is not in passed space.
|
|
1313
|
+
return undefined;
|
|
1314
|
+
}
|
|
1315
|
+
const members = await this.getMembers(spaceId);
|
|
1316
|
+
return members?.items.find(member => member.user.id === userId);
|
|
1317
|
+
}
|
|
1318
|
+
handleNewRole(ev) {
|
|
1319
|
+
const collection = this.roles.get(ev.spaceId);
|
|
1320
|
+
collection.set(ev.role);
|
|
1321
|
+
this.list.get(ev.spaceId).roles = collection.items;
|
|
1322
|
+
}
|
|
1323
|
+
handleNewRoom(ev) {
|
|
1324
|
+
this.rooms.get(ev.spaceId)?.set(ev.summary);
|
|
1325
|
+
this.roomIdToSpaceId.set([ev.summary.id, ev.spaceId]);
|
|
1326
|
+
}
|
|
1327
|
+
handleRoomUpdated(ev) {
|
|
1328
|
+
if (ev.room.spaceId && this.rooms.has(ev.room.spaceId)) {
|
|
1329
|
+
const rooms = this.rooms.get(ev.room.spaceId);
|
|
1330
|
+
rooms.set({
|
|
1331
|
+
...rooms.get(ev.room.id),
|
|
1332
|
+
name: ev.room.name,
|
|
1333
|
+
description: ev.room.description
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
async handleRoomDeleted(ev) {
|
|
1338
|
+
const spaceId = this.roomIdToSpaceId.get(ev.id);
|
|
1339
|
+
this.roomIdToSpaceId.delete(ev.id);
|
|
1340
|
+
if (!spaceId) {
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
const space = this.list.get(spaceId);
|
|
1344
|
+
let spaceChanged = false;
|
|
1345
|
+
this.rooms.get(spaceId)?.delete(ev.id);
|
|
1346
|
+
if (space.systemRoom === ev.id) {
|
|
1347
|
+
space.systemRoom = null;
|
|
1348
|
+
spaceChanged = true;
|
|
1349
|
+
}
|
|
1350
|
+
if (space.defaultRooms.includes(ev.id)) {
|
|
1351
|
+
space.defaultRooms = space.defaultRooms.filter(roomId => roomId !== ev.id);
|
|
1352
|
+
spaceChanged = true;
|
|
1353
|
+
}
|
|
1354
|
+
if (spaceChanged) {
|
|
1355
|
+
this.list.set(space);
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
handleRoleDeleted(ev) {
|
|
1359
|
+
const collection = this.roles.get(ev.spaceId);
|
|
1360
|
+
collection.delete(ev.id);
|
|
1361
|
+
this.list.get(ev.spaceId).roles = collection.items;
|
|
1362
|
+
}
|
|
1363
|
+
handleSpaceUpdated(ev) {
|
|
1364
|
+
this.list.set(ev.space);
|
|
1365
|
+
}
|
|
1366
|
+
handleSpaceDeleted(ev) {
|
|
1367
|
+
const roomIds = this.rooms.get(ev.id)?.items.map(item => item.id) ?? [];
|
|
1368
|
+
this.roomIdToSpaceId.delete(...roomIds);
|
|
1369
|
+
this.roles.delete(ev.id);
|
|
1370
|
+
this.members.delete(ev.id);
|
|
1371
|
+
this.membersPromises.forget(ev.id);
|
|
1372
|
+
this.rooms.delete(ev.id);
|
|
1373
|
+
this.roomsPromises.forget(ev.id);
|
|
1374
|
+
this.list.delete(ev.id);
|
|
1375
|
+
}
|
|
1376
|
+
handleSpaceJoined(ev) {
|
|
1377
|
+
this.addJoinedSpaces(ev.space);
|
|
1378
|
+
}
|
|
1379
|
+
addJoinedSpaces(...spaces) {
|
|
1380
|
+
this.roles.set(...spaces.map(space => [space.id, new ObservableIndexedObjectCollection('id', space.roles)]));
|
|
1381
|
+
this.list.set(...spaces);
|
|
1382
|
+
}
|
|
1383
|
+
handleSpaceMemberJoined(ev) {
|
|
1384
|
+
if (this.members.has(ev.spaceId)) {
|
|
1385
|
+
this.members.get(ev.spaceId).set(ev.member);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
handleSpaceMemberLeft(ev) {
|
|
1389
|
+
if (this.members.has(ev.spaceId)) {
|
|
1390
|
+
this.members.get(ev.spaceId).delete(ev.userId);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
handleSpaceMembers(ev) {
|
|
1394
|
+
if (!this.members.has(ev.id)) {
|
|
1395
|
+
this.members.set([ev.id, new ObservableIndexedObjectCollection(member => member?.user.id, ev.members)]);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
handleSpaceRooms(ev) {
|
|
1399
|
+
if (!this.rooms.has(ev.id)) {
|
|
1400
|
+
this.rooms.set([ev.id, new ObservableIndexedObjectCollection('id', ev.summaries)]);
|
|
1401
|
+
ev.summaries.forEach(summary => this.roomIdToSpaceId.set([summary.id, ev.id]));
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
handleSpaceMemberUpdated(ev) {
|
|
1405
|
+
if (this.members.has(ev.spaceId)) {
|
|
1406
|
+
const members = this.members.get(ev.spaceId);
|
|
1407
|
+
const member = members.get(ev.userId);
|
|
1408
|
+
members.set({
|
|
1409
|
+
...ev.member,
|
|
1410
|
+
user: member.user
|
|
1411
|
+
});
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
handleRoleUpdated(ev) {
|
|
1415
|
+
const roles = this.roles.get(ev.spaceId);
|
|
1416
|
+
const oldRole = roles.get(ev.role.id);
|
|
1417
|
+
const newRole = ev.role;
|
|
1418
|
+
const rolesToUpdate = [newRole];
|
|
1419
|
+
if (oldRole.priority !== newRole.priority) {
|
|
1420
|
+
rolesToUpdate.push(...reorderRolesOnPriorityUpdate(roles.items, oldRole, newRole));
|
|
1421
|
+
}
|
|
1422
|
+
this.roles.get(ev.spaceId).set(...rolesToUpdate);
|
|
1423
|
+
}
|
|
1424
|
+
handleSession(ev) {
|
|
1425
|
+
this.list.deleteAll();
|
|
1426
|
+
this.roles.deleteAll();
|
|
1427
|
+
this.rooms.deleteAll();
|
|
1428
|
+
this.roomsPromises.forgetAll();
|
|
1429
|
+
this.members.deleteAll();
|
|
1430
|
+
this.membersPromises.forgetAll();
|
|
1431
|
+
this.roomIdToSpaceId.deleteAll();
|
|
1432
|
+
this.addJoinedSpaces(...ev.state.spaces);
|
|
1433
|
+
this.deferredSession.resolve();
|
|
1434
|
+
}
|
|
1435
|
+
handleUserUpdated(ev) {
|
|
1436
|
+
this.members.items.forEach(members => {
|
|
1437
|
+
const member = members.get(ev.user.id);
|
|
1438
|
+
if (!member) {
|
|
1439
|
+
// Skip space; updated user is not here
|
|
1440
|
+
return;
|
|
1441
|
+
}
|
|
1442
|
+
members.set({
|
|
1443
|
+
...member,
|
|
1444
|
+
user: ev.user
|
|
1445
|
+
});
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
;// CONCATENATED MODULE: ./src/Permissions.ts
|
|
1450
|
+
function Permissions_defineProperty(obj, key, value) { key = Permissions_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
1451
|
+
function Permissions_toPropertyKey(arg) { var key = Permissions_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
1452
|
+
function Permissions_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
1453
|
+
let Layer = /*#__PURE__*/function (Layer) {
|
|
1454
|
+
Layer[Layer["Global"] = 0] = "Global";
|
|
1455
|
+
Layer[Layer["Space"] = 1] = "Space";
|
|
1456
|
+
Layer[Layer["Room"] = 2] = "Room";
|
|
1457
|
+
Layer[Layer["Topic"] = 3] = "Topic";
|
|
1458
|
+
return Layer;
|
|
1459
|
+
}({});
|
|
1460
|
+
class PermissionDefinition {
|
|
1461
|
+
constructor() {
|
|
1462
|
+
Permissions_defineProperty(this, "value", void 0);
|
|
1463
|
+
Permissions_defineProperty(this, "maxLayer", void 0);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
class Permissions {
|
|
1467
|
+
static getNames() {
|
|
1468
|
+
return Object.keys(this.list);
|
|
1469
|
+
}
|
|
1470
|
+
static getByName(name) {
|
|
1471
|
+
return this.list[name];
|
|
1472
|
+
}
|
|
1473
|
+
static canBeDefinedOnLayer(permissionName, layer) {
|
|
1474
|
+
const def = this.getByName(permissionName);
|
|
1475
|
+
if (!def) {
|
|
1476
|
+
throw new Error(`Invalid permission name: ${permissionName}`);
|
|
1477
|
+
}
|
|
1478
|
+
return layer <= this.getByName(permissionName).maxLayer;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
Permissions_defineProperty(Permissions, "list", {
|
|
1482
|
+
Root: {
|
|
1483
|
+
value: 1 << 0,
|
|
1484
|
+
maxLayer: Layer.Room
|
|
1485
|
+
},
|
|
1486
|
+
CreateSpaces: {
|
|
1487
|
+
value: 1 << 1,
|
|
1488
|
+
maxLayer: Layer.Global
|
|
1489
|
+
},
|
|
1490
|
+
ManageSpace: {
|
|
1491
|
+
value: 1 << 2,
|
|
1492
|
+
maxLayer: Layer.Space
|
|
1493
|
+
},
|
|
1494
|
+
ManageSpaceRoles: {
|
|
1495
|
+
value: 1 << 3,
|
|
1496
|
+
maxLayer: Layer.Space
|
|
1497
|
+
},
|
|
1498
|
+
ManageRoom: {
|
|
1499
|
+
value: 1 << 4,
|
|
1500
|
+
maxLayer: Layer.Room
|
|
1501
|
+
},
|
|
1502
|
+
CreateTopics: {
|
|
1503
|
+
value: 1 << 5,
|
|
1504
|
+
maxLayer: Layer.Room
|
|
1505
|
+
},
|
|
1506
|
+
ManageTopic: {
|
|
1507
|
+
value: 1 << 6,
|
|
1508
|
+
maxLayer: Layer.Topic
|
|
1509
|
+
},
|
|
1510
|
+
ManageSpaceMembers: {
|
|
1511
|
+
value: 1 << 7,
|
|
1512
|
+
maxLayer: Layer.Space
|
|
1513
|
+
},
|
|
1514
|
+
ManageRoomMembers: {
|
|
1515
|
+
value: 1 << 8,
|
|
1516
|
+
maxLayer: Layer.Room
|
|
1517
|
+
},
|
|
1518
|
+
CreateMessages: {
|
|
1519
|
+
value: 1 << 9,
|
|
1520
|
+
maxLayer: Layer.Topic
|
|
1521
|
+
},
|
|
1522
|
+
ManagePermissions: {
|
|
1523
|
+
value: 1 << 10,
|
|
1524
|
+
maxLayer: Layer.Topic
|
|
1525
|
+
},
|
|
1526
|
+
CreateSpaceRooms: {
|
|
1527
|
+
value: 1 << 11,
|
|
1528
|
+
maxLayer: Layer.Space
|
|
1529
|
+
},
|
|
1530
|
+
ManageSpaceRooms: {
|
|
1531
|
+
value: 1 << 12,
|
|
1532
|
+
maxLayer: Layer.Space
|
|
1533
|
+
},
|
|
1534
|
+
CreateEmoticons: {
|
|
1535
|
+
value: 1 << 13,
|
|
1536
|
+
maxLayer: Layer.Space
|
|
1537
|
+
},
|
|
1538
|
+
ManageEmoticon: {
|
|
1539
|
+
value: 1 << 14,
|
|
1540
|
+
maxLayer: Layer.Space
|
|
1541
|
+
},
|
|
1542
|
+
ManageBan: {
|
|
1543
|
+
value: 1 << 15,
|
|
1544
|
+
maxLayer: Layer.Room
|
|
1545
|
+
},
|
|
1546
|
+
Kick: {
|
|
1547
|
+
value: 1 << 16,
|
|
1548
|
+
maxLayer: Layer.Room
|
|
1549
|
+
},
|
|
1550
|
+
ChangeOwnNick: {
|
|
1551
|
+
value: 1 << 17,
|
|
1552
|
+
maxLayer: Layer.Space
|
|
1553
|
+
}
|
|
1554
|
+
});
|
|
1555
|
+
;// CONCATENATED MODULE: ./src/state-tracker/PermissionsManager.ts
|
|
1556
|
+
function PermissionsManager_defineProperty(obj, key, value) { key = PermissionsManager_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
1557
|
+
function PermissionsManager_toPropertyKey(arg) { var key = PermissionsManager_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
1558
|
+
function PermissionsManager_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
1559
|
+
|
|
1560
|
+
|
|
1561
|
+
|
|
1562
|
+
|
|
1563
|
+
const getOvId = (location, target) => [location.spaceId, location.roomId, location.topicId, target?.type, target?.userId, target?.roleId].filter(Boolean).join('/');
|
|
1564
|
+
const getOvIdByObject = overwrites => getOvId(overwrites.location, overwrites.target);
|
|
1565
|
+
class PermissionsManager extends EventTarget {
|
|
1566
|
+
constructor(tracker) {
|
|
1567
|
+
super();
|
|
1568
|
+
this.tracker = tracker;
|
|
1569
|
+
PermissionsManager_defineProperty(this, "overwrites", new IndexedCollection());
|
|
1570
|
+
PermissionsManager_defineProperty(this, "overwritesPromises", new PromiseRegistry());
|
|
1571
|
+
this.tracker.client.on('PermissionOverwrites', ev => this.handlePermissionOverwrites(ev));
|
|
1572
|
+
this.tracker.client.on('PermissionOverwritesUpdated', ev => this.handlePermissionOverwrites(ev));
|
|
1573
|
+
this.tracker.client.on('SpaceDeleted', ev => this.handleSpaceDeleted(ev));
|
|
1574
|
+
this.tracker.client.on('SpaceLeft', ev => this.handleSpaceDeleted(ev));
|
|
1575
|
+
this.tracker.client.on('RoomDeleted', ev => this.handleRoomDeleted(ev));
|
|
1576
|
+
this.tracker.client.on('RoomLeft', ev => this.handleRoomDeleted(ev));
|
|
1577
|
+
this.tracker.client.on('TopicDeleted', ev => this.handleTopicDeleted(ev));
|
|
1578
|
+
this.tracker.client.on('RoleDeleted', ev => this.handleRoleDeleted(ev));
|
|
1579
|
+
this.tracker.client.on('SpaceMemberUpdated', ev => this.handleSpaceMemberUpdated(ev));
|
|
1580
|
+
this.tracker.client.on('RoomMemberUpdated', ev => this.handleRoomMemberUpdated(ev));
|
|
1581
|
+
this.tracker.client.on('Session', ev => this.handleSession(ev));
|
|
1582
|
+
}
|
|
1583
|
+
async getOverwrites(location, target) {
|
|
1584
|
+
this.validateLocation(location);
|
|
1585
|
+
const id = getOvId(location, target);
|
|
1586
|
+
if (this.overwritesPromises.notExist(id)) {
|
|
1587
|
+
this.overwritesPromises.registerByFunction(async () => {
|
|
1588
|
+
const result = await this.tracker.client.send('GetPermissionOverwrites', {
|
|
1589
|
+
location,
|
|
1590
|
+
target
|
|
1591
|
+
});
|
|
1592
|
+
if (result.error) {
|
|
1593
|
+
throw result.error;
|
|
1594
|
+
}
|
|
1595
|
+
this.handlePermissionOverwrites(result.data);
|
|
1596
|
+
}, id);
|
|
1597
|
+
}
|
|
1598
|
+
await this.overwritesPromises.get(id);
|
|
1599
|
+
return this.overwrites.get(id);
|
|
1600
|
+
}
|
|
1601
|
+
on(eventName, handler) {
|
|
1602
|
+
return super.on(eventName, handler);
|
|
1603
|
+
}
|
|
1604
|
+
async check(permissionNames, location) {
|
|
1605
|
+
if (!permissionNames.length) {
|
|
1606
|
+
throw new Error('Permission names array cannot be empty');
|
|
1607
|
+
}
|
|
1608
|
+
const ownedPermissions = await this.calculatePermissions(location);
|
|
1609
|
+
const missing = [];
|
|
1610
|
+
permissionNames.forEach(name => {
|
|
1611
|
+
if (~ownedPermissions & Permissions.getByName(name).value) {
|
|
1612
|
+
missing.push(name);
|
|
1613
|
+
}
|
|
1614
|
+
});
|
|
1615
|
+
return {
|
|
1616
|
+
ok: missing.length === 0,
|
|
1617
|
+
hasAll: missing.length === 0,
|
|
1618
|
+
hasAny: missing.length < permissionNames.length,
|
|
1619
|
+
missing
|
|
1620
|
+
};
|
|
1621
|
+
}
|
|
1622
|
+
async calculatePermissions(location) {
|
|
1623
|
+
this.validateLocation(location);
|
|
1624
|
+
const userId = (await this.tracker.getMe()).id;
|
|
1625
|
+
const [spaceMember, roomMember] = await this.fetchMembersOrFail(location);
|
|
1626
|
+
const userRoles = [...(spaceMember?.roles ?? []), ...(roomMember?.roles ?? [])];
|
|
1627
|
+
const promises = [
|
|
1628
|
+
// Global user overwrites
|
|
1629
|
+
this.getOverwrites({}, {
|
|
1630
|
+
type: 'User',
|
|
1631
|
+
userId
|
|
1632
|
+
}).then(v => v.overwrites)];
|
|
1633
|
+
if (location.spaceId && (await this.tracker.spaces.get())?.has(location.spaceId)) {
|
|
1634
|
+
const filterLocation = {
|
|
1635
|
+
spaceId: location.spaceId
|
|
1636
|
+
};
|
|
1637
|
+
promises.push(this.collectRoleOverwrites(filterLocation, userRoles));
|
|
1638
|
+
promises.push(this.getOverwrites(filterLocation, {
|
|
1639
|
+
type: 'User',
|
|
1640
|
+
userId
|
|
1641
|
+
}).then(v => v.overwrites));
|
|
1642
|
+
}
|
|
1643
|
+
if (location.roomId && (await this.tracker.rooms.get())?.has(location.roomId)) {
|
|
1644
|
+
const filterLocation = {
|
|
1645
|
+
spaceId: location.spaceId,
|
|
1646
|
+
roomId: location.roomId
|
|
1647
|
+
};
|
|
1648
|
+
if (userRoles.length) {
|
|
1649
|
+
promises.push(this.collectRoleOverwrites(filterLocation, userRoles));
|
|
1650
|
+
}
|
|
1651
|
+
promises.push(this.getOverwrites(filterLocation, {
|
|
1652
|
+
type: 'User',
|
|
1653
|
+
userId
|
|
1654
|
+
}).then(v => v.overwrites));
|
|
1655
|
+
}
|
|
1656
|
+
if (location.topicId && (await this.tracker.rooms.getTopics(location.roomId))?.has(location.topicId)) {
|
|
1657
|
+
if (userRoles.length) {
|
|
1658
|
+
promises.push(this.collectRoleOverwrites(location, userRoles));
|
|
1659
|
+
}
|
|
1660
|
+
promises.push(this.getOverwrites(location, {
|
|
1661
|
+
type: 'User',
|
|
1662
|
+
userId
|
|
1663
|
+
}).then(v => v.overwrites));
|
|
1664
|
+
}
|
|
1665
|
+
return this.resolveOverwritesHierarchy(await Promise.all(promises));
|
|
1666
|
+
}
|
|
1667
|
+
handlePermissionOverwrites(ev) {
|
|
1668
|
+
this.overwrites.set([getOvIdByObject(ev), ev]);
|
|
1669
|
+
this.emit('change');
|
|
1670
|
+
}
|
|
1671
|
+
handleSpaceDeleted(ev) {
|
|
1672
|
+
const ids = this.deleteOverwritesByIdPrefix(getOvId({
|
|
1673
|
+
spaceId: ev.id
|
|
1674
|
+
}));
|
|
1675
|
+
this.overwritesPromises.forget(...ids);
|
|
1676
|
+
}
|
|
1677
|
+
async handleRoomDeleted(ev) {
|
|
1678
|
+
const room = (await this.tracker.rooms.get()).get(ev.id);
|
|
1679
|
+
if (room) {
|
|
1680
|
+
const ids = this.deleteOverwritesByIdPrefix(getOvId({
|
|
1681
|
+
spaceId: room.spaceId,
|
|
1682
|
+
roomId: room.id
|
|
1683
|
+
}));
|
|
1684
|
+
this.overwritesPromises.forget(...ids);
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
handleTopicDeleted(ev) {
|
|
1688
|
+
const ids = this.deleteOverwritesByIdPrefix(getOvId(ev.location));
|
|
1689
|
+
this.overwritesPromises.forget(...ids);
|
|
1690
|
+
}
|
|
1691
|
+
handleRoleDeleted(ev) {
|
|
1692
|
+
const ids = this.deleteOverwritesByIdPrefix(getOvId({
|
|
1693
|
+
spaceId: ev.spaceId
|
|
1694
|
+
}, {
|
|
1695
|
+
type: 'Role',
|
|
1696
|
+
roleId: ev.id
|
|
1697
|
+
}));
|
|
1698
|
+
this.overwritesPromises.forget(...ids);
|
|
1699
|
+
}
|
|
1700
|
+
handleSpaceMemberUpdated(ev) {
|
|
1701
|
+
if (ev.userId === this.tracker.me?.id) {
|
|
1702
|
+
// User roles in space could potentially have changed
|
|
1703
|
+
this.emit('change');
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
handleRoomMemberUpdated(ev) {
|
|
1707
|
+
if (ev.userId === this.tracker.me?.id) {
|
|
1708
|
+
// User roles in room could potentially have changed
|
|
1709
|
+
this.emit('change');
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
/**
|
|
1714
|
+
* @return Matched and deleted ids
|
|
1715
|
+
*/
|
|
1716
|
+
deleteOverwritesByIdPrefix(prefix) {
|
|
1717
|
+
const ids = [];
|
|
1718
|
+
this.overwrites.items.forEach(overwrites => {
|
|
1719
|
+
const id = getOvIdByObject(overwrites);
|
|
1720
|
+
if (id.startsWith(prefix)) {
|
|
1721
|
+
ids.push(id);
|
|
1722
|
+
this.overwrites.delete(id);
|
|
1723
|
+
}
|
|
1724
|
+
});
|
|
1725
|
+
return ids;
|
|
1726
|
+
}
|
|
1727
|
+
async collectRoleOverwrites(location, userRoles) {
|
|
1728
|
+
const roleOverwrites = await Promise.all(userRoles.map(roleId => this.getOverwrites(location, {
|
|
1729
|
+
type: 'Role',
|
|
1730
|
+
roleId
|
|
1731
|
+
})));
|
|
1732
|
+
return this.resolveOverwritesFromRolesByOrder(location.spaceId, roleOverwrites);
|
|
1733
|
+
}
|
|
1734
|
+
async resolveOverwritesFromRolesByOrder(spaceId, overwrites) {
|
|
1735
|
+
let allows = 0,
|
|
1736
|
+
denies = 0;
|
|
1737
|
+
const roles = await this.tracker.spaces.getRoles(spaceId);
|
|
1738
|
+
const sortedOverwrites = overwrites.sort((a, b) => roles.get(a.target.roleId).priority - roles.get(b.target.roleId).priority);
|
|
1739
|
+
|
|
1740
|
+
// Max length of bit word
|
|
1741
|
+
const permissionsLength = overwrites.reduce((previousValue, currentValue) => Math.max(previousValue, currentValue.overwrites.allow?.toString(2).length ?? 0, currentValue.overwrites.deny?.toString(2).length ?? 0), 0);
|
|
1742
|
+
sortedOverwrites.forEach(overwriteEvent => {
|
|
1743
|
+
const overwrites = overwriteEvent.overwrites;
|
|
1744
|
+
const revDecDenies = overwrites.deny?.toString(2).split('').reverse().join('') ?? '';
|
|
1745
|
+
const revDecAllows = overwrites.allow?.toString(2).split('').reverse().join('') ?? '';
|
|
1746
|
+
for (let i = 0; i < permissionsLength; i++) {
|
|
1747
|
+
const deny = parseInt(revDecDenies[i] ?? '0');
|
|
1748
|
+
const allow = parseInt(revDecAllows[i] ?? '0');
|
|
1749
|
+
if (deny) {
|
|
1750
|
+
denies |= 1 << i;
|
|
1751
|
+
}
|
|
1752
|
+
if (allow) {
|
|
1753
|
+
allows |= 1 << i;
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
});
|
|
1757
|
+
return {
|
|
1758
|
+
allow: allows,
|
|
1759
|
+
deny: denies
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
resolveOverwritesHierarchy(permissionOverwritesValues) {
|
|
1763
|
+
let result = 0;
|
|
1764
|
+
for (const value of permissionOverwritesValues) {
|
|
1765
|
+
if (value.allow & Permissions.getByName('Root').value) {
|
|
1766
|
+
return this.getRootAccessValue();
|
|
1767
|
+
}
|
|
1768
|
+
result = result & ~value.deny | value.allow;
|
|
1769
|
+
}
|
|
1770
|
+
return result;
|
|
1771
|
+
}
|
|
1772
|
+
getRootAccessValue() {
|
|
1773
|
+
let result = 0;
|
|
1774
|
+
for (const name of Permissions.getNames()) {
|
|
1775
|
+
result |= Permissions.getByName(name).value;
|
|
1776
|
+
}
|
|
1777
|
+
return result;
|
|
1778
|
+
}
|
|
1779
|
+
async fetchMembersOrFail(location) {
|
|
1780
|
+
const results = await Promise.all([location.spaceId ? this.tracker.spaces.getMe(location.spaceId) : null, location.roomId ? this.tracker.rooms.getMe(location.roomId) : null]);
|
|
1781
|
+
const spaceFail = location.spaceId && !results[0];
|
|
1782
|
+
const roomFail = location.roomId && !results[1];
|
|
1783
|
+
if (spaceFail || roomFail) {
|
|
1784
|
+
const layer = spaceFail ? `space (${location.spaceId})` : `room (${location.roomId})`;
|
|
1785
|
+
throw new Error(`Attempting to calculate permissions for a ${layer} that the user does not belong to`);
|
|
1786
|
+
}
|
|
1787
|
+
return results;
|
|
1788
|
+
}
|
|
1789
|
+
validateLocation(location) {
|
|
1790
|
+
if (location.topicId && !location.roomId) {
|
|
1791
|
+
throw new Error('Corrupted arguments hierarchy');
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
handleSession(ev) {
|
|
1795
|
+
this.overwrites.deleteAll();
|
|
1796
|
+
this.overwritesPromises.forgetAll();
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
;// CONCATENATED MODULE: ./src/state-tracker/EmoticonsManager.ts
|
|
1800
|
+
function EmoticonsManager_defineProperty(obj, key, value) { key = EmoticonsManager_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
1801
|
+
function EmoticonsManager_toPropertyKey(arg) { var key = EmoticonsManager_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
1802
|
+
function EmoticonsManager_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
1803
|
+
|
|
1804
|
+
|
|
1805
|
+
const GLOBAL_KEY = 'global';
|
|
1806
|
+
class EmoticonsManager {
|
|
1807
|
+
constructor(tracker) {
|
|
1808
|
+
this.tracker = tracker;
|
|
1809
|
+
EmoticonsManager_defineProperty(this, "list", new IndexedCollection());
|
|
1810
|
+
EmoticonsManager_defineProperty(this, "emoticonsPromises", new PromiseRegistry());
|
|
1811
|
+
this.tracker.client.on('Emoticons', ev => this.handleEmoticons(ev));
|
|
1812
|
+
this.tracker.client.on('NewEmoticon', ev => this.handleNewEmoticon(ev));
|
|
1813
|
+
this.tracker.client.on('EmoticonDeleted', ev => this.handleEmoticonDeleted(ev));
|
|
1814
|
+
this.tracker.client.on('SpaceDeleted', ev => this.handleSpaceDeleted(ev));
|
|
1815
|
+
this.tracker.client.on('Session', () => this.handleSession());
|
|
1816
|
+
}
|
|
1817
|
+
async get(spaceId) {
|
|
1818
|
+
if (this.emoticonsPromises.notExist(spaceId)) {
|
|
1819
|
+
this.emoticonsPromises.registerByFunction(async () => {
|
|
1820
|
+
const result = await this.tracker.client.send('GetEmoticons', {
|
|
1821
|
+
spaceId
|
|
1822
|
+
});
|
|
1823
|
+
if (result.error) {
|
|
1824
|
+
throw result.error;
|
|
1825
|
+
}
|
|
1826
|
+
this.handleEmoticons(result.data);
|
|
1827
|
+
}, spaceId ?? GLOBAL_KEY);
|
|
1828
|
+
}
|
|
1829
|
+
await this.emoticonsPromises.get(spaceId);
|
|
1830
|
+
return this.list.get(spaceId);
|
|
1831
|
+
}
|
|
1832
|
+
handleEmoticons(event) {
|
|
1833
|
+
const spaceId = event.location.spaceId ?? GLOBAL_KEY;
|
|
1834
|
+
if (!this.list.has(spaceId)) {
|
|
1835
|
+
this.list.set([spaceId, new ObservableIndexedObjectCollection('id')]);
|
|
1836
|
+
}
|
|
1837
|
+
const collection = this.list.get(spaceId);
|
|
1838
|
+
collection.set(...event.emoticons);
|
|
1839
|
+
}
|
|
1840
|
+
handleNewEmoticon(ev) {
|
|
1841
|
+
const collection = this.list.get(ev.emoticon.spaceId ?? GLOBAL_KEY);
|
|
1842
|
+
collection?.set(ev.emoticon);
|
|
1843
|
+
}
|
|
1844
|
+
handleEmoticonDeleted(ev) {
|
|
1845
|
+
const collection = this.list.get(ev.spaceId ?? GLOBAL_KEY);
|
|
1846
|
+
collection?.delete(ev.emoticonId);
|
|
1847
|
+
}
|
|
1848
|
+
handleSpaceDeleted(event) {
|
|
1849
|
+
this.list.delete(event.id);
|
|
1850
|
+
}
|
|
1851
|
+
handleSession() {
|
|
1852
|
+
this.list.deleteAll();
|
|
1853
|
+
this.emoticonsPromises.forgetAll();
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
;// CONCATENATED MODULE: ./src/state-tracker/UsersManager.ts
|
|
1857
|
+
function UsersManager_defineProperty(obj, key, value) { key = UsersManager_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
1858
|
+
function UsersManager_toPropertyKey(arg) { var key = UsersManager_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
1859
|
+
function UsersManager_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
1860
|
+
|
|
1861
|
+
|
|
1862
|
+
class UsersManager {
|
|
1863
|
+
constructor(tracker) {
|
|
1864
|
+
this.tracker = tracker;
|
|
1865
|
+
UsersManager_defineProperty(this, "users", new ObservableIndexedObjectCollection('id'));
|
|
1866
|
+
// RoomMemberUpdated & SpaceMemberUpdated events are not contains user object
|
|
1867
|
+
tracker.client.on('UserUpdated', event => this.handleUsers([event.user]));
|
|
1868
|
+
tracker.client.on('RoomMemberJoined', event => this.handleMembers([event.member]));
|
|
1869
|
+
tracker.client.on('SpaceMemberJoined', event => this.handleMembers([event.member]));
|
|
1870
|
+
tracker.client.on('SpaceMembers', event => this.handleMembers(event.members));
|
|
1871
|
+
tracker.client.on('RoomMembers', event => this.handleMembers(event.members));
|
|
1872
|
+
tracker.client.on('Messages', event => this.handleUsers(event.messages.map(message => message.author.user)));
|
|
1873
|
+
tracker.client.on('NewMessage', event => this.handleUsers([event.message.author.user]));
|
|
1874
|
+
tracker.client.on('Session', event => this.handleSession(event));
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
/**
|
|
1878
|
+
* Get all available (cached) user objects at once.
|
|
1879
|
+
*/
|
|
1880
|
+
async getAvailable() {
|
|
1881
|
+
return this.users;
|
|
1882
|
+
}
|
|
1883
|
+
handleMembers(members) {
|
|
1884
|
+
this.users.set(...members.map(extractUserFromMember));
|
|
1885
|
+
}
|
|
1886
|
+
handleUsers(users) {
|
|
1887
|
+
this.users.set(...users);
|
|
1888
|
+
}
|
|
1889
|
+
handleSession(session) {
|
|
1890
|
+
this.users.deleteAll();
|
|
1891
|
+
this.users.set(session.user);
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
;// CONCATENATED MODULE: ./src/state-tracker/ChatStateTracker.ts
|
|
1895
|
+
function ChatStateTracker_defineProperty(obj, key, value) { key = ChatStateTracker_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
1896
|
+
function ChatStateTracker_toPropertyKey(arg) { var key = ChatStateTracker_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
1897
|
+
function ChatStateTracker_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
1898
|
+
|
|
1899
|
+
|
|
1900
|
+
|
|
1901
|
+
|
|
1902
|
+
|
|
1903
|
+
|
|
1904
|
+
class ChatStateTracker {
|
|
1905
|
+
constructor(client) {
|
|
1906
|
+
this.client = client;
|
|
1907
|
+
/**
|
|
1908
|
+
* State of your permissions.
|
|
1909
|
+
*/
|
|
1910
|
+
ChatStateTracker_defineProperty(this, "permissions", new PermissionsManager(this));
|
|
1911
|
+
/**
|
|
1912
|
+
* State of the rooms you are in.
|
|
1913
|
+
*/
|
|
1914
|
+
ChatStateTracker_defineProperty(this, "rooms", new RoomsManager(this));
|
|
1915
|
+
/**
|
|
1916
|
+
* State of the spaces you are in.
|
|
1917
|
+
*/
|
|
1918
|
+
ChatStateTracker_defineProperty(this, "spaces", new SpacesManager(this));
|
|
1919
|
+
/**
|
|
1920
|
+
* State of the emoticons (global and space-related).
|
|
1921
|
+
*/
|
|
1922
|
+
ChatStateTracker_defineProperty(this, "emoticons", new EmoticonsManager(this));
|
|
1923
|
+
/**
|
|
1924
|
+
* Users related state.
|
|
1925
|
+
*/
|
|
1926
|
+
ChatStateTracker_defineProperty(this, "users", new UsersManager(this));
|
|
1927
|
+
ChatStateTracker_defineProperty(this, "_me", null);
|
|
1928
|
+
ChatStateTracker_defineProperty(this, "deferredSession", new DeferredTask());
|
|
1929
|
+
this.client.on('Session', ev => this.handleSession(ev));
|
|
1930
|
+
}
|
|
1931
|
+
get me() {
|
|
1932
|
+
return this._me;
|
|
1933
|
+
}
|
|
1934
|
+
async getMe() {
|
|
1935
|
+
await this.deferredSession.promise;
|
|
1936
|
+
return this._me;
|
|
1937
|
+
}
|
|
1938
|
+
handleSession(ev) {
|
|
1939
|
+
this._me = ev.user;
|
|
1940
|
+
this.deferredSession.resolve();
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
;// CONCATENATED MODULE: ./src/WebSocketChatClient.ts
|
|
1944
|
+
function WebSocketChatClient_defineProperty(obj, key, value) { key = WebSocketChatClient_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
1945
|
+
function WebSocketChatClient_toPropertyKey(arg) { var key = WebSocketChatClient_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
1946
|
+
function WebSocketChatClient_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
1947
|
+
|
|
1948
|
+
|
|
1949
|
+
var WebSocketChatClientEvent = /*#__PURE__*/function (WebSocketChatClientEvent) {
|
|
1950
|
+
WebSocketChatClientEvent["connect"] = "connect";
|
|
1951
|
+
WebSocketChatClientEvent["disconnect"] = "disconnect";
|
|
1952
|
+
WebSocketChatClientEvent["message"] = "message";
|
|
1953
|
+
WebSocketChatClientEvent["error"] = "error";
|
|
1954
|
+
return WebSocketChatClientEvent;
|
|
1955
|
+
}(WebSocketChatClientEvent || {});
|
|
1956
|
+
class WebSocketChatClient extends AbstractChatClient {
|
|
1957
|
+
constructor(options) {
|
|
1958
|
+
super();
|
|
1959
|
+
this.options = options;
|
|
1960
|
+
WebSocketChatClient_defineProperty(this, "Event", WebSocketChatClientEvent);
|
|
1961
|
+
WebSocketChatClient_defineProperty(this, "state", void 0);
|
|
1962
|
+
WebSocketChatClient_defineProperty(this, "ws", null);
|
|
1963
|
+
WebSocketChatClient_defineProperty(this, "sendQueue", []);
|
|
1964
|
+
WebSocketChatClient_defineProperty(this, "connectingTimeoutId", void 0);
|
|
1965
|
+
WebSocketChatClient_defineProperty(this, "authenticated", void 0);
|
|
1966
|
+
WebSocketChatClient_defineProperty(this, "authenticatedResolvers", void 0);
|
|
1967
|
+
if (this.options.stateTracking ?? true) {
|
|
1968
|
+
this.state = new ChatStateTracker(this);
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
async connect() {
|
|
1972
|
+
const params = new URLSearchParams(this.options.queryParams ?? {});
|
|
1973
|
+
params.set('token', this.options.token);
|
|
1974
|
+
this.ws = new WebSocket(`${this.options.url}?${params}`);
|
|
1975
|
+
this.ws.onclose = ev => this.onClose(ev);
|
|
1976
|
+
this.ws.onmessage = ev => this.onMessage(ev);
|
|
1977
|
+
this.connectingTimeoutId = setTimeout(() => this.triggerConnectionTimeout(), this.options.connectingTimeoutMs ?? 10000);
|
|
1978
|
+
this.authenticated = false;
|
|
1979
|
+
return new Promise((...args) => this.authenticatedResolvers = args);
|
|
1980
|
+
}
|
|
1981
|
+
disconnect() {
|
|
1982
|
+
this.sendQueue = [];
|
|
1983
|
+
this.ws?.close();
|
|
1984
|
+
this.ws = null;
|
|
1985
|
+
}
|
|
1986
|
+
async send(commandType, commandData) {
|
|
1987
|
+
if (!this.ws || [this.ws.CLOSED, this.ws.CLOSING].includes(this.ws.readyState)) {
|
|
1988
|
+
throw new Error('Cannot send; close or closing connection state');
|
|
1989
|
+
}
|
|
1990
|
+
const envelope = this.createEnvelope(commandType, commandData);
|
|
1991
|
+
const promise = this.createPromiseFromCommandEnvelope(envelope);
|
|
1992
|
+
if (this.ws.readyState === this.ws.CONNECTING || !this.authenticated) {
|
|
1993
|
+
this.sendQueue.push(envelope);
|
|
1994
|
+
return promise;
|
|
1995
|
+
}
|
|
1996
|
+
if (this.ws.readyState !== this.ws.OPEN) {
|
|
1997
|
+
throw new Error(`Invalid websocket state=${this.ws.readyState}`);
|
|
1998
|
+
}
|
|
1999
|
+
this.sendEnvelope(envelope);
|
|
2000
|
+
return promise;
|
|
2001
|
+
}
|
|
2002
|
+
sendEnvelope(envelope) {
|
|
2003
|
+
this.ws.send(JSON.stringify(envelope));
|
|
2004
|
+
}
|
|
2005
|
+
onMessage(event) {
|
|
2006
|
+
const envelope = JSON.parse(event.data);
|
|
2007
|
+
this.handleIncomingEnvelope(envelope);
|
|
2008
|
+
this.emit(envelope.type, envelope.data);
|
|
2009
|
+
this.emit(this.Event.message, envelope);
|
|
2010
|
+
|
|
2011
|
+
// Login successfully
|
|
2012
|
+
if (!this.authenticated) {
|
|
2013
|
+
const isAuthenticated = envelope.type !== 'Bye';
|
|
2014
|
+
this.authenticated = isAuthenticated;
|
|
2015
|
+
if (isAuthenticated) {
|
|
2016
|
+
this.authenticatedResolvers[0]();
|
|
2017
|
+
this.emit(this.Event.connect);
|
|
2018
|
+
this.sendFromQueue();
|
|
2019
|
+
} else {
|
|
2020
|
+
this.authenticatedResolvers[1](envelope.data);
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
onClose(event) {
|
|
2025
|
+
clearTimeout(this.connectingTimeoutId);
|
|
2026
|
+
const reconnect = event.code !== 1000; // Connection was closed because of error
|
|
2027
|
+
if (reconnect) {
|
|
2028
|
+
this.connect();
|
|
2029
|
+
}
|
|
2030
|
+
this.emit(this.Event.disconnect, reconnect);
|
|
2031
|
+
}
|
|
2032
|
+
sendFromQueue() {
|
|
2033
|
+
// Send awaiting data to server
|
|
2034
|
+
let lastDelay = 0;
|
|
2035
|
+
for (const dataIndex in this.sendQueue) {
|
|
2036
|
+
const envelope = this.sendQueue[dataIndex];
|
|
2037
|
+
setTimeout(() => this.sendEnvelope(envelope), lastDelay);
|
|
2038
|
+
lastDelay += this.options.awaitQueueSendDelayMs ?? 500;
|
|
2039
|
+
}
|
|
2040
|
+
this.sendQueue = [];
|
|
2041
|
+
clearTimeout(this.connectingTimeoutId);
|
|
2042
|
+
}
|
|
2043
|
+
triggerConnectionTimeout() {
|
|
2044
|
+
this.disconnect();
|
|
2045
|
+
this.emit(this.Event.error, new Error('Connection timeout'));
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
;// CONCATENATED MODULE: ./src/WebApiChatClient.ts
|
|
2049
|
+
function WebApiChatClient_defineProperty(obj, key, value) { key = WebApiChatClient_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2050
|
+
function WebApiChatClient_toPropertyKey(arg) { var key = WebApiChatClient_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
2051
|
+
function WebApiChatClient_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
2052
|
+
|
|
2053
|
+
var WebApiChatClientEvent = /*#__PURE__*/function (WebApiChatClientEvent) {
|
|
2054
|
+
WebApiChatClientEvent["message"] = "message";
|
|
2055
|
+
WebApiChatClientEvent["error"] = "error";
|
|
2056
|
+
WebApiChatClientEvent["destroy"] = "destroy";
|
|
2057
|
+
return WebApiChatClientEvent;
|
|
2058
|
+
}(WebApiChatClientEvent || {});
|
|
2059
|
+
class WebApiChatClient extends AbstractChatClient {
|
|
2060
|
+
constructor(options) {
|
|
2061
|
+
super();
|
|
2062
|
+
this.options = options;
|
|
2063
|
+
WebApiChatClient_defineProperty(this, "Event", WebApiChatClientEvent);
|
|
2064
|
+
WebApiChatClient_defineProperty(this, "sendStack", void 0);
|
|
2065
|
+
}
|
|
2066
|
+
async send(commandType, commandData) {
|
|
2067
|
+
const envelope = this.createEnvelope(commandType, commandData);
|
|
2068
|
+
this.sendStack.push({
|
|
2069
|
+
data: envelope,
|
|
2070
|
+
attempts: 0,
|
|
2071
|
+
lastTimeoutId: null
|
|
2072
|
+
});
|
|
2073
|
+
this.makeApiCall(this.sendStack.length - 1);
|
|
2074
|
+
return this.createPromiseFromCommandEnvelope(envelope);
|
|
2075
|
+
}
|
|
2076
|
+
destroy() {
|
|
2077
|
+
// Cancel all awaiting requests
|
|
2078
|
+
this.sendStack.forEach(item => {
|
|
2079
|
+
if (item.lastTimeoutId) {
|
|
2080
|
+
clearTimeout(item.lastTimeoutId);
|
|
2081
|
+
}
|
|
2082
|
+
this.awaitingResponse.delete(item.data.ref);
|
|
2083
|
+
});
|
|
2084
|
+
this.sendStack = [];
|
|
2085
|
+
this.emit(this.Event.destroy, false);
|
|
2086
|
+
}
|
|
2087
|
+
async onMessage(reqId, response) {
|
|
2088
|
+
this.sendStack.splice(reqId, 1);
|
|
2089
|
+
const envelope = await response.json();
|
|
2090
|
+
this.handleIncomingEnvelope(envelope);
|
|
2091
|
+
this.emit(envelope.type, envelope.data);
|
|
2092
|
+
this.emit(this.Event.message, envelope);
|
|
2093
|
+
}
|
|
2094
|
+
onError(reqId, body) {
|
|
2095
|
+
if (this.sendStack[reqId].attempts >= (this.options.attemptsToSend ?? 10)) {
|
|
2096
|
+
this.sendStack.splice(reqId, 1);
|
|
2097
|
+
this.handleEnvelopeSendError(this.sendStack[reqId].data, new Error(`Cannot send ${body}; aborting after reaching the maximum connection errors`));
|
|
2098
|
+
return;
|
|
2099
|
+
}
|
|
2100
|
+
this.sendStack[reqId].lastTimeoutId = setTimeout(() => this.makeApiCall(reqId), this.options.attemptDelayMs ?? 3000);
|
|
2101
|
+
}
|
|
2102
|
+
makeApiCall(reqId) {
|
|
2103
|
+
this.sendStack[reqId].attempts++;
|
|
2104
|
+
const bodyJson = JSON.stringify(this.sendStack[reqId].data);
|
|
2105
|
+
const headers = {
|
|
2106
|
+
'Content-Type': 'application/json',
|
|
2107
|
+
Accept: 'application/json'
|
|
2108
|
+
};
|
|
2109
|
+
headers.Authorization = `Bearer ${this.options.token}`;
|
|
2110
|
+
const params = new URLSearchParams(this.options.queryParams ?? {});
|
|
2111
|
+
const url = `${this.options.url}${params ? '?' + params : ''}`;
|
|
2112
|
+
fetch(url, {
|
|
2113
|
+
headers,
|
|
2114
|
+
body: bodyJson,
|
|
2115
|
+
method: 'POST'
|
|
2116
|
+
}).then(response => this.onMessage(reqId, response)).catch(() => this.onError(reqId, bodyJson));
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
;// CONCATENATED MODULE: ./src/AbstractRestClient.ts
|
|
2120
|
+
function AbstractRestClient_defineProperty(obj, key, value) { key = AbstractRestClient_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2121
|
+
function AbstractRestClient_toPropertyKey(arg) { var key = AbstractRestClient_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
2122
|
+
function AbstractRestClient_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
2123
|
+
class AbstractRestClient {
|
|
2124
|
+
constructor(options) {
|
|
2125
|
+
this.options = options;
|
|
2126
|
+
AbstractRestClient_defineProperty(this, "defaultUrl", void 0);
|
|
2127
|
+
}
|
|
2128
|
+
async send(method, uri, data = undefined) {
|
|
2129
|
+
let url = this.getUrl(uri);
|
|
2130
|
+
let body = undefined;
|
|
2131
|
+
if (data) {
|
|
2132
|
+
if (['GET', 'DELETE'].includes(method)) {
|
|
2133
|
+
url += new URLSearchParams(data).toString();
|
|
2134
|
+
} else {
|
|
2135
|
+
body = JSON.stringify(data);
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
const headers = {
|
|
2139
|
+
'Content-Type': 'application/json',
|
|
2140
|
+
Accept: 'application/json',
|
|
2141
|
+
...this.getAuthHeaders()
|
|
2142
|
+
};
|
|
2143
|
+
const result = await fetch(url, {
|
|
2144
|
+
method,
|
|
2145
|
+
body,
|
|
2146
|
+
headers
|
|
2147
|
+
});
|
|
2148
|
+
return this.convertFetchResponse(result);
|
|
2149
|
+
}
|
|
2150
|
+
getAuthHeaders() {
|
|
2151
|
+
const headers = {};
|
|
2152
|
+
if (this.options.token) {
|
|
2153
|
+
headers.Authorization = `Bearer ${this.options.token}`;
|
|
2154
|
+
}
|
|
2155
|
+
return headers;
|
|
2156
|
+
}
|
|
2157
|
+
getUrl(uri) {
|
|
2158
|
+
return this.removeEndingSlash(this.options.url ?? this.defaultUrl) + '/' + this.removeStartingSlash(uri);
|
|
2159
|
+
}
|
|
2160
|
+
async convertFetchResponse(result) {
|
|
2161
|
+
return {
|
|
2162
|
+
ok: result.ok,
|
|
2163
|
+
status: result.status,
|
|
2164
|
+
data: result.headers.get('content-type')?.includes('json') ? await result.json() : await result.text()
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
2167
|
+
removeStartingSlash(text) {
|
|
2168
|
+
return text.replace(/^\/+/, '');
|
|
2169
|
+
}
|
|
2170
|
+
removeEndingSlash(text) {
|
|
2171
|
+
return text.replace(/\/+$/, '');
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
;// CONCATENATED MODULE: ./src/AuthClient.ts
|
|
2175
|
+
function AuthClient_defineProperty(obj, key, value) { key = AuthClient_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2176
|
+
function AuthClient_toPropertyKey(arg) { var key = AuthClient_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
2177
|
+
function AuthClient_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
2178
|
+
|
|
2179
|
+
class AuthClient extends AbstractRestClient {
|
|
2180
|
+
constructor(...args) {
|
|
2181
|
+
super(...args);
|
|
2182
|
+
AuthClient_defineProperty(this, "defaultUrl", 'https://polfan.pl/webservice/api');
|
|
2183
|
+
}
|
|
2184
|
+
static async createToken(login, password, clientName = 'pserv-js-client') {
|
|
2185
|
+
const response = await new AuthClient({
|
|
2186
|
+
token: null
|
|
2187
|
+
}).send('POST', 'auth/tokens', {
|
|
2188
|
+
login,
|
|
2189
|
+
password,
|
|
2190
|
+
client_name: clientName
|
|
2191
|
+
});
|
|
2192
|
+
if (response.ok) {
|
|
2193
|
+
return response.data;
|
|
2194
|
+
}
|
|
2195
|
+
throw new Error(`Cannot create user token: ${response.data.errors[0]}`);
|
|
2196
|
+
}
|
|
2197
|
+
async deleteToken(token) {
|
|
2198
|
+
const response = await this.send('DELETE', `auth/tokens/${token}`);
|
|
2199
|
+
if (!response.ok) {
|
|
2200
|
+
throw new Error(`Cannot delete access token: ${response.data.errors[0]}`);
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
async getMe() {
|
|
2204
|
+
const response = await this.send('GET', 'auth/me');
|
|
2205
|
+
if (response.ok) {
|
|
2206
|
+
response.data.id = response.data.id.toString();
|
|
2207
|
+
return response.data;
|
|
2208
|
+
}
|
|
2209
|
+
throw new Error(`Cannot get current user account: ${response.data.errors[0]}`);
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
;// CONCATENATED MODULE: ./src/FilesClient.ts
|
|
2213
|
+
function FilesClient_defineProperty(obj, key, value) { key = FilesClient_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2214
|
+
function FilesClient_toPropertyKey(arg) { var key = FilesClient_toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
2215
|
+
function FilesClient_toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
2216
|
+
|
|
2217
|
+
class FilesClient extends AbstractRestClient {
|
|
2218
|
+
constructor(...args) {
|
|
2219
|
+
super(...args);
|
|
2220
|
+
FilesClient_defineProperty(this, "defaultUrl", 'https://polfan.pl/webservice/api/files');
|
|
2221
|
+
}
|
|
2222
|
+
async uploadFile(file) {
|
|
2223
|
+
const formData = new FormData();
|
|
2224
|
+
formData.append('file', file);
|
|
2225
|
+
let headers = {
|
|
2226
|
+
...this.getAuthHeaders(),
|
|
2227
|
+
Accept: 'application/json'
|
|
2228
|
+
};
|
|
2229
|
+
const response = await fetch(this.defaultUrl, {
|
|
2230
|
+
method: 'POST',
|
|
2231
|
+
body: formData,
|
|
2232
|
+
headers
|
|
2233
|
+
});
|
|
2234
|
+
return this.convertFetchResponse(response);
|
|
2235
|
+
}
|
|
2236
|
+
async getFileMetadata(id) {
|
|
2237
|
+
return this.send('GET', '/' + id);
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
;// CONCATENATED MODULE: ./src/index.ts
|
|
2241
|
+
|
|
2242
|
+
|
|
2243
|
+
|
|
2244
|
+
|
|
2245
|
+
|
|
2246
|
+
|
|
2247
|
+
|
|
2248
|
+
|
|
2249
|
+
module.exports = __webpack_exports__;
|
|
2250
|
+
/******/ })()
|
|
2251
|
+
;
|
|
2252
|
+
//# sourceMappingURL=index.cjs.js.map
|