@player-tools/devtools-messenger 0.8.0-next.0 → 0.8.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/dist/cjs/index.cjs +107 -74
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.legacy-esm.js +107 -74
- package/dist/index.mjs +107 -74
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
- package/src/__tests__/helpers/index.ts +12 -2
- package/src/__tests__/index.test.ts +200 -52
- package/src/index.ts +134 -106
- package/types/index.d.ts +10 -5
package/src/index.ts
CHANGED
|
@@ -12,7 +12,13 @@ import type {
|
|
|
12
12
|
TransactionMetadata,
|
|
13
13
|
} from "@player-tools/devtools-types";
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const internalEvents: Array<InternalEvent<BaseEvent<string, unknown>>["type"]> =
|
|
16
|
+
[
|
|
17
|
+
"MESSENGER_BEACON",
|
|
18
|
+
"MESSENGER_DISCONNECT",
|
|
19
|
+
"MESSENGER_REQUEST_LOST_EVENTS",
|
|
20
|
+
"MESSENGER_EVENT_BATCH",
|
|
21
|
+
];
|
|
16
22
|
|
|
17
23
|
/**
|
|
18
24
|
* Messenger<EventsType>
|
|
@@ -57,14 +63,14 @@ const counters: Record<string, number> = {};
|
|
|
57
63
|
* ```
|
|
58
64
|
*/
|
|
59
65
|
export class Messenger<T extends BaseEvent<string, unknown>> {
|
|
60
|
-
/** static record of events
|
|
61
|
-
private static
|
|
66
|
+
/** static record of events by isntance ID */
|
|
67
|
+
private static events: Record<
|
|
62
68
|
string,
|
|
63
|
-
Array<BaseEvent<string, unknown
|
|
69
|
+
Array<MessageEvent<BaseEvent<string, unknown>>>
|
|
64
70
|
> = {};
|
|
65
71
|
|
|
66
|
-
/** connections record */
|
|
67
|
-
private connections: Record<string, Connection
|
|
72
|
+
/** static connections record by instance ID */
|
|
73
|
+
private static connections: Record<string, Record<string, Connection>> = {};
|
|
68
74
|
|
|
69
75
|
/** beacon interval */
|
|
70
76
|
private beaconInterval: NodeJS.Timeout | null = null;
|
|
@@ -96,11 +102,6 @@ export class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
96
102
|
|
|
97
103
|
// add listener:
|
|
98
104
|
this.options.addListener(this.handleMessage);
|
|
99
|
-
|
|
100
|
-
// if events for this context don't exist, create an empty array
|
|
101
|
-
if (!(Messenger.contextEvents[this.options.context] as T[])) {
|
|
102
|
-
(Messenger.contextEvents[this.options.context] as T[]) = [];
|
|
103
|
-
}
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
private log(message: string) {
|
|
@@ -111,40 +112,62 @@ export class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
115
|
+
private getConnection(id: string) {
|
|
116
|
+
if (!Messenger.connections[this.id]) {
|
|
117
|
+
Messenger.connections[this.id] = {};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return Messenger.connections[this.id][id];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private addConnection(id: string) {
|
|
124
|
+
Messenger.connections[this.id][id] = {
|
|
125
|
+
id,
|
|
126
|
+
messagesReceived: 0,
|
|
127
|
+
messagesSent: 0,
|
|
128
|
+
desync: false,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private getEvents() {
|
|
133
|
+
if (!Messenger.events[this.id]) {
|
|
134
|
+
Messenger.events[this.id] = [];
|
|
135
|
+
}
|
|
122
136
|
|
|
137
|
+
return Messenger.events[this.id] as unknown as MessengerEvent<T>[];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private addEvent(event: MessengerEvent<T>) {
|
|
141
|
+
const events = this.getEvents();
|
|
142
|
+
events.push(event);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** generate a sequential id for each non-internal message */
|
|
146
|
+
private getTransactionID(message: MessengerEvent<T>) {
|
|
123
147
|
if (
|
|
124
|
-
!target ||
|
|
148
|
+
!message.target ||
|
|
125
149
|
internalEvents.includes(message.type as InternalEvent<T>["type"])
|
|
126
150
|
) {
|
|
127
151
|
return -1;
|
|
128
152
|
}
|
|
129
153
|
|
|
130
|
-
if (!
|
|
131
|
-
|
|
154
|
+
if (!this.getConnection(message.target)) {
|
|
155
|
+
this.addConnection(message.target);
|
|
132
156
|
}
|
|
133
157
|
|
|
134
|
-
|
|
158
|
+
const connection = this.getConnection(message.target);
|
|
159
|
+
connection.messagesSent += 1;
|
|
160
|
+
return connection.messagesSent;
|
|
135
161
|
}
|
|
136
162
|
|
|
137
|
-
private addTransactionMetadata(
|
|
138
|
-
event: MessengerEvent<T>,
|
|
139
|
-
target?: string
|
|
140
|
-
): Transaction<T> {
|
|
163
|
+
private addTransactionMetadata(event: MessengerEvent<T>): Transaction<T> {
|
|
141
164
|
const metadata = {
|
|
142
165
|
_messenger_: true,
|
|
143
|
-
id: this.getTransactionID(event
|
|
166
|
+
id: this.getTransactionID(event),
|
|
144
167
|
sender: this.id,
|
|
145
168
|
timestamp: Date.now(),
|
|
146
169
|
context: this.options.context,
|
|
147
|
-
...(target && { target }),
|
|
170
|
+
...(event.target && { target: event.target }),
|
|
148
171
|
};
|
|
149
172
|
|
|
150
173
|
return {
|
|
@@ -171,8 +194,9 @@ export class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
171
194
|
const isFromMessenger = parsed._messenger_;
|
|
172
195
|
const isFromSelf = parsed.sender === this.id;
|
|
173
196
|
const isFromSameContext = parsed.context === this.options.context;
|
|
174
|
-
const isTargetingOthers = parsed.target
|
|
175
|
-
const
|
|
197
|
+
const isTargetingOthers = parsed.target ? parsed.target !== this.id : false;
|
|
198
|
+
const connection = this.getConnection(parsed.sender);
|
|
199
|
+
const isKnownConnection = Boolean(connection);
|
|
176
200
|
|
|
177
201
|
if (
|
|
178
202
|
!isFromMessenger ||
|
|
@@ -200,25 +224,29 @@ export class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
200
224
|
if (isKnownConnection) {
|
|
201
225
|
const isBatch = parsed.type === "MESSENGER_EVENT_BATCH";
|
|
202
226
|
|
|
203
|
-
// if batch, get the first message id, so we can check for missing messages:
|
|
204
227
|
const transactionID = isBatch
|
|
205
228
|
? (parsed.payload as EventsBatchEvent<T>["payload"]).events[0].id
|
|
206
229
|
: parsed.id;
|
|
207
230
|
|
|
208
|
-
const {
|
|
231
|
+
const { messagesReceived, desync } = connection;
|
|
209
232
|
|
|
210
233
|
// if we already received this message, ignore:
|
|
211
|
-
if (transactionID <=
|
|
234
|
+
if (transactionID > -1 && transactionID <= messagesReceived) {
|
|
212
235
|
return;
|
|
213
236
|
}
|
|
214
237
|
|
|
215
238
|
// if we missed messages, request them, unless we already did:
|
|
216
|
-
if (
|
|
239
|
+
if (
|
|
240
|
+
!desync &&
|
|
241
|
+
transactionID > -1 &&
|
|
242
|
+
transactionID > messagesReceived + 1
|
|
243
|
+
) {
|
|
217
244
|
const message: RequestLostEventsEvent = {
|
|
218
245
|
type: "MESSENGER_REQUEST_LOST_EVENTS",
|
|
219
246
|
payload: {
|
|
220
|
-
|
|
247
|
+
messagesReceived,
|
|
221
248
|
},
|
|
249
|
+
target: parsed.sender,
|
|
222
250
|
};
|
|
223
251
|
|
|
224
252
|
this.options.sendMessage(this.addTransactionMetadata(message));
|
|
@@ -228,7 +256,7 @@ export class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
228
256
|
);
|
|
229
257
|
|
|
230
258
|
// set desync, so we don't request again:
|
|
231
|
-
|
|
259
|
+
connection.desync = true;
|
|
232
260
|
|
|
233
261
|
// don't process this message, since we requested missing ones:
|
|
234
262
|
return;
|
|
@@ -236,17 +264,13 @@ export class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
236
264
|
|
|
237
265
|
if (isBatch) {
|
|
238
266
|
// clear desync flag on event batch:
|
|
239
|
-
|
|
267
|
+
connection.desync = false;
|
|
268
|
+
connection.messagesReceived += (
|
|
269
|
+
parsed.payload as EventsBatchEvent<T>["payload"]
|
|
270
|
+
).events.length;
|
|
271
|
+
} else {
|
|
272
|
+
connection.messagesReceived += 1;
|
|
240
273
|
}
|
|
241
|
-
|
|
242
|
-
// if batch, get the last message id:
|
|
243
|
-
const newLastMessageIdx = isBatch
|
|
244
|
-
? (parsed.payload as EventsBatchEvent<T>["payload"]).events.slice(-1)[0]
|
|
245
|
-
.id
|
|
246
|
-
: parsed.id;
|
|
247
|
-
|
|
248
|
-
// update last received message id:
|
|
249
|
-
this.connections[parsed.sender].lastReceivedMessageId = newLastMessageIdx;
|
|
250
274
|
}
|
|
251
275
|
|
|
252
276
|
this.options.messageCallback(parsed);
|
|
@@ -257,74 +281,76 @@ export class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
257
281
|
}
|
|
258
282
|
|
|
259
283
|
private handleBeaconMessage(parsed: Transaction<T>) {
|
|
260
|
-
|
|
261
|
-
|
|
284
|
+
if (this.getConnection(parsed.sender)) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
this.addConnection(parsed.sender);
|
|
289
|
+
const events = this.getEvents();
|
|
290
|
+
|
|
291
|
+
if (events.length > 0) {
|
|
262
292
|
const message: EventsBatchEvent<T> = {
|
|
263
293
|
type: "MESSENGER_EVENT_BATCH",
|
|
264
294
|
payload: {
|
|
265
|
-
events: (
|
|
266
|
-
(event) => this.addTransactionMetadata(event, parsed.sender)
|
|
267
|
-
),
|
|
295
|
+
events: events.map((event) => this.addTransactionMetadata(event)),
|
|
268
296
|
},
|
|
297
|
+
target: parsed.sender,
|
|
269
298
|
};
|
|
270
299
|
|
|
271
|
-
this.options.sendMessage(
|
|
272
|
-
this.addTransactionMetadata(message, parsed.sender)
|
|
273
|
-
);
|
|
300
|
+
this.options.sendMessage(this.addTransactionMetadata(message));
|
|
274
301
|
|
|
275
302
|
this.log(
|
|
276
|
-
`messages [0 - ${
|
|
277
|
-
|
|
278
|
-
}
|
|
303
|
+
`messages [0 - ${events.length - 1}] sent to ${parsed.context}:${
|
|
304
|
+
parsed.sender
|
|
305
|
+
}`
|
|
279
306
|
);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const newConnection: Connection = {
|
|
283
|
-
id: parsed.sender,
|
|
284
|
-
lastSentMessageId:
|
|
285
|
-
(Messenger.contextEvents[this.options.context] as T[]).length - 1,
|
|
286
|
-
lastReceivedMessageId: -1,
|
|
287
|
-
desync: false,
|
|
288
|
-
};
|
|
289
307
|
|
|
290
|
-
|
|
308
|
+
const connection = this.getConnection(parsed.sender);
|
|
309
|
+
connection.messagesSent = events.length;
|
|
310
|
+
}
|
|
291
311
|
|
|
292
312
|
this.log(`new connection added - ${parsed.context}:${parsed.sender}`);
|
|
293
313
|
}
|
|
294
314
|
|
|
295
315
|
private handleLostEventsRequest(parsed: Transaction<T>) {
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
316
|
+
const connection = this.getConnection(parsed.sender);
|
|
317
|
+
const events = this.getEvents();
|
|
318
|
+
|
|
319
|
+
if (!connection || events.length === 0) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const missingEvents = events.slice(connection.messagesSent, events.length);
|
|
324
|
+
|
|
325
|
+
if (missingEvents.length === 0) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
305
328
|
|
|
306
329
|
const message: EventsBatchEvent<T> = {
|
|
307
330
|
type: "MESSENGER_EVENT_BATCH",
|
|
308
331
|
payload: {
|
|
309
332
|
events: missingEvents.map((event) =>
|
|
310
|
-
this.addTransactionMetadata(event
|
|
333
|
+
this.addTransactionMetadata(event)
|
|
311
334
|
),
|
|
312
335
|
},
|
|
336
|
+
target: parsed.sender,
|
|
313
337
|
};
|
|
314
338
|
|
|
315
339
|
this.options.sendMessage(this.addTransactionMetadata(message));
|
|
316
340
|
|
|
341
|
+
connection.messagesSent = events.length;
|
|
342
|
+
|
|
317
343
|
this.log(
|
|
318
|
-
`messages [0 - ${
|
|
319
|
-
|
|
320
|
-
}
|
|
344
|
+
`messages [0 - ${events.length - 1}] sent to ${parsed.context}:${
|
|
345
|
+
parsed.sender
|
|
346
|
+
}`
|
|
321
347
|
);
|
|
322
348
|
}
|
|
323
349
|
|
|
324
350
|
private handleDisconnectMessage(
|
|
325
351
|
parsed: TransactionMetadata & MessengerEvent<T>
|
|
326
352
|
) {
|
|
327
|
-
delete
|
|
353
|
+
delete Messenger.connections[parsed.sender];
|
|
328
354
|
|
|
329
355
|
this.log(`disconnected - ${parsed.context}:${parsed.sender}`);
|
|
330
356
|
}
|
|
@@ -333,26 +359,24 @@ export class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
333
359
|
const parsed: T =
|
|
334
360
|
typeof message === "string" ? JSON.parse(message) : message;
|
|
335
361
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
);
|
|
355
|
-
});
|
|
362
|
+
this.addEvent(parsed);
|
|
363
|
+
|
|
364
|
+
const target = parsed.target || null;
|
|
365
|
+
const msg = this.addTransactionMetadata(parsed);
|
|
366
|
+
const connection = target ? this.getConnection(target) : null;
|
|
367
|
+
|
|
368
|
+
if (connection) {
|
|
369
|
+
connection.messagesSent += 1;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
this.options.sendMessage(msg).catch(() => {
|
|
373
|
+
this.options.handleFailedMessage?.(msg);
|
|
374
|
+
|
|
375
|
+
this.log(
|
|
376
|
+
`failed to send message: ${
|
|
377
|
+
(parsed as BaseEvent<string, unknown>).type
|
|
378
|
+
} from ${this.id} to ${target || "all"}`
|
|
379
|
+
);
|
|
356
380
|
});
|
|
357
381
|
}
|
|
358
382
|
|
|
@@ -363,19 +387,23 @@ export class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
363
387
|
|
|
364
388
|
this.options.removeListener(this.handleMessage);
|
|
365
389
|
|
|
366
|
-
Object.keys(
|
|
390
|
+
Object.keys(Messenger.connections).forEach((connection) => {
|
|
367
391
|
const event: DisconnectEvent = {
|
|
368
392
|
type: "MESSENGER_DISCONNECT",
|
|
369
393
|
payload: null,
|
|
394
|
+
target: connection,
|
|
370
395
|
};
|
|
371
|
-
const message = this.addTransactionMetadata(event
|
|
396
|
+
const message = this.addTransactionMetadata(event);
|
|
372
397
|
this.options.sendMessage(message);
|
|
373
398
|
});
|
|
374
399
|
|
|
400
|
+
Messenger.reset();
|
|
375
401
|
this.log("destroyed");
|
|
376
402
|
}
|
|
377
403
|
|
|
378
|
-
static
|
|
379
|
-
|
|
404
|
+
/** reset static records */
|
|
405
|
+
static reset() {
|
|
406
|
+
Messenger.events = {};
|
|
407
|
+
Messenger.connections = {};
|
|
380
408
|
}
|
|
381
409
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -43,10 +43,10 @@ import type { BaseEvent, MessengerOptions } from "@player-tools/devtools-types";
|
|
|
43
43
|
*/
|
|
44
44
|
export declare class Messenger<T extends BaseEvent<string, unknown>> {
|
|
45
45
|
private options;
|
|
46
|
-
/** static record of events
|
|
47
|
-
private static
|
|
48
|
-
/** connections record */
|
|
49
|
-
private connections;
|
|
46
|
+
/** static record of events by isntance ID */
|
|
47
|
+
private static events;
|
|
48
|
+
/** static connections record by instance ID */
|
|
49
|
+
private static connections;
|
|
50
50
|
/** beacon interval */
|
|
51
51
|
private beaconInterval;
|
|
52
52
|
/** time between beacons milliseconds */
|
|
@@ -57,6 +57,10 @@ export declare class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
57
57
|
private id;
|
|
58
58
|
constructor(options: MessengerOptions<T>);
|
|
59
59
|
private log;
|
|
60
|
+
private getConnection;
|
|
61
|
+
private addConnection;
|
|
62
|
+
private getEvents;
|
|
63
|
+
private addEvent;
|
|
60
64
|
/** generate a sequential id for each non-internal message */
|
|
61
65
|
private getTransactionID;
|
|
62
66
|
private addTransactionMetadata;
|
|
@@ -69,6 +73,7 @@ export declare class Messenger<T extends BaseEvent<string, unknown>> {
|
|
|
69
73
|
private handleDisconnectMessage;
|
|
70
74
|
sendMessage(message: T | string): void;
|
|
71
75
|
destroy(): void;
|
|
72
|
-
static
|
|
76
|
+
/** reset static records */
|
|
77
|
+
static reset(): void;
|
|
73
78
|
}
|
|
74
79
|
//# sourceMappingURL=index.d.ts.map
|