polfan-server-js-client 0.2.57 → 0.2.58
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/workspace.xml +4 -0
- package/babel.config.js +1 -1
- package/build/index.cjs.js +73 -66
- package/build/index.cjs.js.map +1 -1
- package/build/index.umd.js +1 -1
- package/build/index.umd.js.map +1 -1
- package/build/types/IndexedObjectCollection.d.ts +4 -4
- package/build/types/state-tracker/TopicHistoryWindow.d.ts +18 -8
- package/package.json +2 -2
- package/src/IndexedObjectCollection.ts +4 -4
- package/src/state-tracker/TopicHistoryWindow.ts +60 -39
- package/tests/history-window.test.ts +1 -1
|
@@ -10,7 +10,7 @@ export declare class IndexedCollection<KeyT, ValueT> {
|
|
|
10
10
|
delete(...ids: KeyT[]): void;
|
|
11
11
|
deleteAll(): void;
|
|
12
12
|
findBy(field: keyof ValueT, valueToFind: any, limit?: number): IndexedCollection<KeyT, ValueT>;
|
|
13
|
-
|
|
13
|
+
createMirror(): IndexedCollection<KeyT, ValueT>;
|
|
14
14
|
}
|
|
15
15
|
export declare class IndexedObjectCollection<T> {
|
|
16
16
|
readonly id: keyof T | ((item: T) => any);
|
|
@@ -25,7 +25,7 @@ export declare class IndexedObjectCollection<T> {
|
|
|
25
25
|
delete(...ids: any[]): void;
|
|
26
26
|
deleteAll(): void;
|
|
27
27
|
findBy(field: keyof T, valueToFind: any, limit?: number): IndexedObjectCollection<T>;
|
|
28
|
-
|
|
28
|
+
createMirror(): IndexedObjectCollection<T>;
|
|
29
29
|
protected getId(item: T): any;
|
|
30
30
|
}
|
|
31
31
|
interface ObservableCollectionEvent<KeyT> {
|
|
@@ -38,7 +38,7 @@ export declare class ObservableIndexedCollection<KeyT, ValueT> extends IndexedCo
|
|
|
38
38
|
set(...items: [KeyT, ValueT][]): void;
|
|
39
39
|
delete(...ids: KeyT[]): void;
|
|
40
40
|
deleteAll(): void;
|
|
41
|
-
|
|
41
|
+
createMirror(): ObservableIndexedCollection<KeyT, ValueT>;
|
|
42
42
|
on(eventName: 'change', handler: (ev?: ObservableCollectionEvent<KeyT>) => void): this;
|
|
43
43
|
once(eventName: 'change', handler: (ev?: ObservableCollectionEvent<KeyT>) => void): this;
|
|
44
44
|
off(eventName: string, handler: (ev?: ObservableCollectionEvent<KeyT>) => void): this;
|
|
@@ -50,7 +50,7 @@ export declare class ObservableIndexedObjectCollection<T> extends IndexedObjectC
|
|
|
50
50
|
set(...items: T[]): void;
|
|
51
51
|
delete(...ids: string[]): void;
|
|
52
52
|
deleteAll(): void;
|
|
53
|
-
|
|
53
|
+
createMirror(): IndexedObjectCollection<T>;
|
|
54
54
|
on(eventName: 'change', handler: (ev?: ObservableCollectionEvent<string>) => void): this;
|
|
55
55
|
once(eventName: 'change', handler: (ev?: ObservableCollectionEvent<string>) => void): this;
|
|
56
56
|
off(eventName: string, handler: (ev?: ObservableCollectionEvent<string>) => void): this;
|
|
@@ -26,17 +26,25 @@ export declare abstract class TraversableRemoteCollection<T> extends ObservableI
|
|
|
26
26
|
* Current mode od collection window. To change mode, call one of available fetch methods.
|
|
27
27
|
*/
|
|
28
28
|
get state(): WindowState;
|
|
29
|
+
protected internalState: {
|
|
30
|
+
current: WindowState;
|
|
31
|
+
ongoing?: WindowState;
|
|
32
|
+
limit: number | null;
|
|
33
|
+
oldestId: string | null;
|
|
34
|
+
};
|
|
29
35
|
/**
|
|
30
36
|
* Maximum numer of items stored in window.
|
|
31
37
|
* Null for unlimited.
|
|
32
38
|
*/
|
|
33
|
-
limit: number | null;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
get limit(): number | null;
|
|
40
|
+
/**
|
|
41
|
+
* Maximum numer of items stored in window.
|
|
42
|
+
* Null for unlimited.
|
|
43
|
+
*/
|
|
44
|
+
set limit(value: number | null);
|
|
38
45
|
get hasLatest(): boolean;
|
|
39
46
|
get hasOldest(): boolean;
|
|
47
|
+
abstract createMirror(): IndexedObjectCollection<T>;
|
|
40
48
|
resetToLatest(): Promise<void>;
|
|
41
49
|
fetchPrevious(): Promise<void>;
|
|
42
50
|
fetchNext(): Promise<void>;
|
|
@@ -59,9 +67,11 @@ export declare class TopicHistoryWindow extends TraversableRemoteCollection<Mess
|
|
|
59
67
|
* Reexported available window modes enum.
|
|
60
68
|
*/
|
|
61
69
|
readonly WindowState: typeof WindowState;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
protected internalState: typeof TraversableRemoteCollection<Message>['prototype']['internalState'] & {
|
|
71
|
+
traverseLock: boolean;
|
|
72
|
+
};
|
|
73
|
+
constructor(roomId: string, topicId: string, tracker: ChatStateTracker, bindEvents?: boolean);
|
|
74
|
+
createMirror(): TopicHistoryWindow;
|
|
65
75
|
get isTraverseLocked(): boolean;
|
|
66
76
|
setTraverseLock(lock: boolean): Promise<void>;
|
|
67
77
|
resetToLatest(): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polfan-server-js-client",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.58",
|
|
4
4
|
"description": "JavaScript client library for handling communication with Polfan chat server.",
|
|
5
5
|
"author": "Jarosław Żak",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@babel/plugin-transform-typescript": "^7.20.2",
|
|
32
32
|
"@babel/polyfill": "^7.12.1",
|
|
33
33
|
"@babel/preset-env": "^7.20.2",
|
|
34
|
-
"@babel/preset-typescript": "^7.
|
|
34
|
+
"@babel/preset-typescript": "^7.28.5",
|
|
35
35
|
"@types/jest": "^29.2.5",
|
|
36
36
|
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
|
37
37
|
"@typescript-eslint/parser": "^4.33.0",
|
|
@@ -53,7 +53,7 @@ export class IndexedCollection<KeyT, ValueT> {
|
|
|
53
53
|
return result;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
public
|
|
56
|
+
public createMirror(): IndexedCollection<KeyT, ValueT> {
|
|
57
57
|
const copy = new IndexedCollection<KeyT, ValueT>();
|
|
58
58
|
copy._items = this._items;
|
|
59
59
|
return copy;
|
|
@@ -116,7 +116,7 @@ export class IndexedObjectCollection<T> {
|
|
|
116
116
|
return result;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
public
|
|
119
|
+
public createMirror(): IndexedObjectCollection<T> {
|
|
120
120
|
const copy = new IndexedObjectCollection<T>(this.id);
|
|
121
121
|
copy._items = this._items;
|
|
122
122
|
return copy;
|
|
@@ -163,7 +163,7 @@ export class ObservableIndexedCollection<KeyT, ValueT> extends IndexedCollection
|
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
public
|
|
166
|
+
public createMirror(): ObservableIndexedCollection<KeyT, ValueT> {
|
|
167
167
|
const copy = new ObservableIndexedCollection<KeyT, ValueT>();
|
|
168
168
|
copy.eventTarget = this.eventTarget;
|
|
169
169
|
copy._items = this._items;
|
|
@@ -220,7 +220,7 @@ export class ObservableIndexedObjectCollection<T> extends IndexedObjectCollectio
|
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
public
|
|
223
|
+
public createMirror(): IndexedObjectCollection<T> {
|
|
224
224
|
const copy = new ObservableIndexedObjectCollection<T>(this.id);
|
|
225
225
|
copy.eventTarget = this.eventTarget;
|
|
226
226
|
copy._items = this._items;
|
|
@@ -31,63 +31,80 @@ export abstract class TraversableRemoteCollection<T> extends ObservableIndexedOb
|
|
|
31
31
|
* Current mode od collection window. To change mode, call one of available fetch methods.
|
|
32
32
|
*/
|
|
33
33
|
public get state(): WindowState {
|
|
34
|
-
return this.
|
|
34
|
+
return this.internalState.current;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
protected internalState: {
|
|
38
|
+
current: WindowState,
|
|
39
|
+
ongoing?: WindowState,
|
|
40
|
+
limit: number | null,
|
|
41
|
+
oldestId: string | null,
|
|
42
|
+
} = {
|
|
43
|
+
current: WindowState.LIVE,
|
|
44
|
+
ongoing: undefined,
|
|
45
|
+
limit: 50,
|
|
46
|
+
oldestId: null,
|
|
47
|
+
};
|
|
48
|
+
|
|
37
49
|
/**
|
|
38
50
|
* Maximum numer of items stored in window.
|
|
39
51
|
* Null for unlimited.
|
|
40
52
|
*/
|
|
41
|
-
public limit: number | null
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
protected currentState: WindowState = WindowState.LIVE;
|
|
46
|
-
protected fetchingState: WindowState = undefined;
|
|
53
|
+
public get limit(): number | null {
|
|
54
|
+
return this.internalState.limit;
|
|
55
|
+
}
|
|
47
56
|
|
|
48
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Maximum numer of items stored in window.
|
|
59
|
+
* Null for unlimited.
|
|
60
|
+
*/
|
|
61
|
+
public set limit(value: number | null) {
|
|
62
|
+
this.internalState.limit = value;
|
|
63
|
+
}
|
|
49
64
|
|
|
50
65
|
public get hasLatest(): boolean {
|
|
51
66
|
return [WindowState.LATEST, WindowState.LIVE].includes(this.state);
|
|
52
67
|
}
|
|
53
68
|
|
|
54
69
|
public get hasOldest(): boolean {
|
|
55
|
-
return this.state === WindowState.OLDEST || this.oldestId !== null && this.has(this.oldestId);
|
|
70
|
+
return this.state === WindowState.OLDEST || this.internalState.oldestId !== null && this.has(this.internalState.oldestId);
|
|
56
71
|
}
|
|
57
72
|
|
|
73
|
+
public abstract createMirror(): IndexedObjectCollection<T>;
|
|
74
|
+
|
|
58
75
|
public async resetToLatest(): Promise<void> {
|
|
59
|
-
if (this.
|
|
76
|
+
if (this.internalState.ongoing || this.internalState.current === WindowState.LATEST) {
|
|
60
77
|
return;
|
|
61
78
|
}
|
|
62
79
|
|
|
63
|
-
this.
|
|
80
|
+
this.internalState.ongoing = WindowState.LATEST;
|
|
64
81
|
|
|
65
82
|
let result;
|
|
66
83
|
|
|
67
84
|
try {
|
|
68
85
|
result = await this.fetchLatestItems();
|
|
69
86
|
} finally {
|
|
70
|
-
this.
|
|
87
|
+
this.internalState.ongoing = undefined;
|
|
71
88
|
}
|
|
72
89
|
|
|
73
90
|
this.deleteAll();
|
|
74
91
|
this.addItems(result, 'tail');
|
|
75
|
-
this.
|
|
92
|
+
this.internalState.current = WindowState.LATEST;
|
|
76
93
|
}
|
|
77
94
|
|
|
78
95
|
public async fetchPrevious(): Promise<void> {
|
|
79
|
-
if (this.
|
|
96
|
+
if (this.internalState.ongoing || this.hasOldest) {
|
|
80
97
|
return;
|
|
81
98
|
}
|
|
82
99
|
|
|
83
|
-
this.
|
|
100
|
+
this.internalState.ongoing = WindowState.PAST;
|
|
84
101
|
|
|
85
102
|
let result;
|
|
86
103
|
|
|
87
104
|
try {
|
|
88
105
|
result = await this.fetchItemsBefore();
|
|
89
106
|
} finally {
|
|
90
|
-
this.
|
|
107
|
+
this.internalState.ongoing = undefined;
|
|
91
108
|
}
|
|
92
109
|
|
|
93
110
|
if (! result) {
|
|
@@ -96,13 +113,13 @@ export abstract class TraversableRemoteCollection<T> extends ObservableIndexedOb
|
|
|
96
113
|
|
|
97
114
|
if (! result.length) {
|
|
98
115
|
const firstItem = this.getAt(0);
|
|
99
|
-
this.oldestId = firstItem ? this.getId(firstItem) : null;
|
|
116
|
+
this.internalState.oldestId = firstItem ? this.getId(firstItem) : null;
|
|
100
117
|
|
|
101
118
|
await this.refreshFetchedState();
|
|
102
119
|
|
|
103
120
|
// LATEST state has priority over OLDEST
|
|
104
|
-
if (this.
|
|
105
|
-
this.
|
|
121
|
+
if (this.internalState.current === WindowState.PAST) {
|
|
122
|
+
this.internalState.current = WindowState.OLDEST;
|
|
106
123
|
}
|
|
107
124
|
|
|
108
125
|
return;
|
|
@@ -113,18 +130,18 @@ export abstract class TraversableRemoteCollection<T> extends ObservableIndexedOb
|
|
|
113
130
|
}
|
|
114
131
|
|
|
115
132
|
public async fetchNext(): Promise<void> {
|
|
116
|
-
if (this.
|
|
133
|
+
if (this.internalState.ongoing || this.hasLatest) {
|
|
117
134
|
return;
|
|
118
135
|
}
|
|
119
136
|
|
|
120
|
-
this.
|
|
137
|
+
this.internalState.ongoing = WindowState.PAST;
|
|
121
138
|
|
|
122
139
|
let result;
|
|
123
140
|
|
|
124
141
|
try {
|
|
125
142
|
result = await this.fetchItemsAfter();
|
|
126
143
|
} finally {
|
|
127
|
-
this.
|
|
144
|
+
this.internalState.ongoing = undefined;
|
|
128
145
|
}
|
|
129
146
|
|
|
130
147
|
if (! result) {
|
|
@@ -148,7 +165,7 @@ export abstract class TraversableRemoteCollection<T> extends ObservableIndexedOb
|
|
|
148
165
|
protected abstract isLatestItemLoaded(): Promise<boolean>;
|
|
149
166
|
|
|
150
167
|
protected async refreshFetchedState(): Promise<void> {
|
|
151
|
-
this.
|
|
168
|
+
this.internalState.current = (await this.isLatestItemLoaded()) ? WindowState.LATEST : WindowState.PAST;
|
|
152
169
|
}
|
|
153
170
|
|
|
154
171
|
protected addItems(newItems: T[], to: 'head' | 'tail'): void {
|
|
@@ -190,36 +207,40 @@ export class TopicHistoryWindow extends TraversableRemoteCollection<Message> {
|
|
|
190
207
|
*/
|
|
191
208
|
public readonly WindowState: typeof WindowState = WindowState;
|
|
192
209
|
|
|
193
|
-
|
|
210
|
+
declare protected internalState: typeof TraversableRemoteCollection<Message>['prototype']['internalState'] & {
|
|
211
|
+
traverseLock: boolean,
|
|
212
|
+
};
|
|
194
213
|
|
|
195
214
|
public constructor(
|
|
196
215
|
private roomId: string,
|
|
197
216
|
private topicId: string,
|
|
198
217
|
private tracker: ChatStateTracker,
|
|
218
|
+
bindEvents: boolean = true,
|
|
199
219
|
) {
|
|
200
220
|
super('id');
|
|
201
|
-
|
|
202
|
-
this.
|
|
221
|
+
|
|
222
|
+
this.internalState.traverseLock = false;
|
|
223
|
+
|
|
224
|
+
if (bindEvents) {
|
|
225
|
+
this.tracker.client.on('Session', ev => this.handleSession(ev));
|
|
226
|
+
this.tracker.client.on('NewMessage', ev => this.handleNewMessage(ev));
|
|
227
|
+
}
|
|
203
228
|
}
|
|
204
229
|
|
|
205
|
-
public
|
|
206
|
-
const copy = new TopicHistoryWindow(this.roomId, this.topicId, this.tracker);
|
|
230
|
+
public createMirror(): TopicHistoryWindow {
|
|
231
|
+
const copy = new TopicHistoryWindow(this.roomId, this.topicId, this.tracker, false);
|
|
207
232
|
copy.eventTarget = this.eventTarget;
|
|
208
233
|
copy._items = this._items;
|
|
209
|
-
copy.
|
|
210
|
-
copy.currentState = this.currentState;
|
|
211
|
-
copy.fetchingState = this.fetchingState;
|
|
212
|
-
copy.oldestId = this.oldestId;
|
|
213
|
-
copy.traverseLock = this.traverseLock;
|
|
234
|
+
copy.internalState = this.internalState;
|
|
214
235
|
return copy;
|
|
215
236
|
}
|
|
216
237
|
|
|
217
238
|
public get isTraverseLocked(): boolean {
|
|
218
|
-
return this.traverseLock;
|
|
239
|
+
return this.internalState.traverseLock;
|
|
219
240
|
}
|
|
220
241
|
|
|
221
242
|
public async setTraverseLock(lock: boolean): Promise<void> {
|
|
222
|
-
this.traverseLock = lock;
|
|
243
|
+
this.internalState.traverseLock = lock;
|
|
223
244
|
|
|
224
245
|
if (lock && (this.state !== WindowState.LIVE && this.state !== WindowState.LATEST)) {
|
|
225
246
|
await super.resetToLatest();
|
|
@@ -227,21 +248,21 @@ export class TopicHistoryWindow extends TraversableRemoteCollection<Message> {
|
|
|
227
248
|
}
|
|
228
249
|
|
|
229
250
|
public async resetToLatest(): Promise<void> {
|
|
230
|
-
if (this.traverseLock) {
|
|
251
|
+
if (this.internalState.traverseLock) {
|
|
231
252
|
return;
|
|
232
253
|
}
|
|
233
254
|
return super.resetToLatest();
|
|
234
255
|
}
|
|
235
256
|
|
|
236
257
|
public async fetchNext(): Promise<void> {
|
|
237
|
-
if (this.traverseLock) {
|
|
258
|
+
if (this.internalState.traverseLock) {
|
|
238
259
|
return;
|
|
239
260
|
}
|
|
240
261
|
return super.fetchNext();
|
|
241
262
|
}
|
|
242
263
|
|
|
243
264
|
public async fetchPrevious(): Promise<void> {
|
|
244
|
-
if (this.traverseLock) {
|
|
265
|
+
if (this.internalState.traverseLock) {
|
|
245
266
|
return;
|
|
246
267
|
}
|
|
247
268
|
return super.fetchPrevious();
|
|
@@ -274,7 +295,7 @@ export class TopicHistoryWindow extends TraversableRemoteCollection<Message> {
|
|
|
274
295
|
const rooms = ev.state.rooms;
|
|
275
296
|
|
|
276
297
|
if (rooms.find(room => room.id === this.roomId)) {
|
|
277
|
-
this.resetToLatest();
|
|
298
|
+
void this.resetToLatest();
|
|
278
299
|
} else {
|
|
279
300
|
this.deleteAll();
|
|
280
301
|
}
|
|
@@ -19,7 +19,7 @@ const messages: SimpleMessage[] = [
|
|
|
19
19
|
];
|
|
20
20
|
|
|
21
21
|
class TestableHistoryWindow extends TraversableRemoteCollection<SimpleMessage> {
|
|
22
|
-
public
|
|
22
|
+
public createMirror(): IndexedObjectCollection<SimpleMessage> {
|
|
23
23
|
throw new Error('Method not implemented.');
|
|
24
24
|
}
|
|
25
25
|
|