@player-tools/devtools-messenger 0.5.3--canary.90.2515

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.
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/messenger/src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ Messenger: () => Messenger
34
+ });
35
+ module.exports = __toCommonJS(src_exports);
36
+ var import_tiny_uid = __toESM(require("tiny-uid"));
37
+ var counters = {};
38
+ var Messenger = class _Messenger {
39
+ constructor(options) {
40
+ this.options = options;
41
+ this.id = options.id || (0, import_tiny_uid.default)();
42
+ this.beaconIntervalMS = options.beaconIntervalMS || 1e3;
43
+ this.beaconInterval = setInterval(
44
+ this.beacon.bind(this),
45
+ this.beaconIntervalMS
46
+ );
47
+ this.handleMessage = this._handleMessage.bind(this);
48
+ this.options.addListener(this.handleMessage);
49
+ if (!_Messenger.contextEvents[this.options.context]) {
50
+ _Messenger.contextEvents[this.options.context] = [];
51
+ }
52
+ }
53
+ /** static record of events per context */
54
+ static contextEvents = {};
55
+ /** connections record */
56
+ connections = {};
57
+ /** beacon interval */
58
+ beaconInterval = null;
59
+ /** time between beacons milliseconds */
60
+ beaconIntervalMS;
61
+ /** callback to handle messages, here for instance binding */
62
+ handleMessage;
63
+ /** unique id */
64
+ id;
65
+ log(message) {
66
+ if (this.options.debug) {
67
+ this.options.logger.log(
68
+ `[MESSENGER-${this.id}](${this.options.context}): ${message}`
69
+ );
70
+ }
71
+ }
72
+ /** generate a sequential id for each non-internal message */
73
+ getTransactionID(message, target) {
74
+ const internalEvents = [
75
+ "MESSENGER_BEACON",
76
+ "MESSENGER_DISCONNECT",
77
+ "MESSENGER_REQUEST_LOST_EVENTS",
78
+ "MESSENGER_EVENT_BATCH"
79
+ ];
80
+ if (!target || internalEvents.includes(message.type)) {
81
+ return -1;
82
+ }
83
+ if (!counters[target]) {
84
+ counters[target] = 0;
85
+ }
86
+ return counters[target]++;
87
+ }
88
+ addTransactionMetadata(event, target) {
89
+ const metadata = {
90
+ _messenger_: true,
91
+ id: this.getTransactionID(event, target),
92
+ sender: this.id,
93
+ timestamp: Date.now(),
94
+ context: this.options.context,
95
+ ...target && { target }
96
+ };
97
+ return {
98
+ ...metadata,
99
+ ...event
100
+ };
101
+ }
102
+ /** there is no persistent layer bookkeeping connections,
103
+ * so beacon to inform others of its presence */
104
+ beacon() {
105
+ this.options.sendMessage(
106
+ this.addTransactionMetadata({
107
+ type: "MESSENGER_BEACON",
108
+ payload: null
109
+ })
110
+ );
111
+ }
112
+ _handleMessage(transaction) {
113
+ const parsed = typeof transaction === "string" ? JSON.parse(transaction) : transaction;
114
+ const isFromMessenger = parsed._messenger_;
115
+ const isFromSelf = parsed.sender === this.id;
116
+ const isFromSameContext = parsed.context === this.options.context;
117
+ const isTargetingOthers = parsed.target && parsed.target !== this.id;
118
+ const isKnownConnection = this.connections[parsed.sender];
119
+ if (!isFromMessenger || isFromSelf || isFromSameContext || isTargetingOthers || isKnownConnection && parsed.type === "MESSENGER_BEACON") {
120
+ return;
121
+ }
122
+ const handlers = {
123
+ MESSENGER_BEACON: this.handleBeaconMessage.bind(this),
124
+ MESSENGER_DISCONNECT: this.handleDisconnectMessage.bind(this),
125
+ MESSENGER_REQUEST_LOST_EVENTS: this.handleLostEventsRequest.bind(this)
126
+ };
127
+ const handler = handlers[parsed.type];
128
+ if (handler) {
129
+ handler(parsed);
130
+ return;
131
+ }
132
+ if (isKnownConnection) {
133
+ const isBatch = parsed.type === "MESSENGER_EVENT_BATCH";
134
+ const transactionID = isBatch ? parsed.payload.events[0].id : parsed.id;
135
+ const { lastReceivedMessageId, desync } = this.connections[parsed.sender];
136
+ if (transactionID <= lastReceivedMessageId) {
137
+ return;
138
+ }
139
+ if (!desync && transactionID > lastReceivedMessageId + 1) {
140
+ const message = {
141
+ type: "MESSENGER_REQUEST_LOST_EVENTS",
142
+ payload: {
143
+ lastReceivedMessageId
144
+ }
145
+ };
146
+ this.options.sendMessage(this.addTransactionMetadata(message));
147
+ this.log(
148
+ `requesting lost messages from ${parsed.context}:${parsed.sender}`
149
+ );
150
+ this.connections[parsed.sender].desync = true;
151
+ return;
152
+ }
153
+ if (isBatch) {
154
+ this.connections[parsed.sender].desync = false;
155
+ }
156
+ const newLastMessageIdx = isBatch ? parsed.payload.events.slice(-1)[0].id : parsed.id;
157
+ this.connections[parsed.sender].lastReceivedMessageId = newLastMessageIdx;
158
+ }
159
+ this.options.messageCallback(parsed);
160
+ this.log(
161
+ `message received: ${parsed.type}`
162
+ );
163
+ }
164
+ handleBeaconMessage(parsed) {
165
+ if (_Messenger.contextEvents[this.options.context].length > 0) {
166
+ const message = {
167
+ type: "MESSENGER_EVENT_BATCH",
168
+ payload: {
169
+ events: _Messenger.contextEvents[this.options.context].map(
170
+ (event) => this.addTransactionMetadata(event, parsed.sender)
171
+ )
172
+ }
173
+ };
174
+ this.options.sendMessage(
175
+ this.addTransactionMetadata(message, parsed.sender)
176
+ );
177
+ this.log(
178
+ `messages [0 - ${_Messenger.contextEvents[this.options.context].length - 1}] sent to ${parsed.context}:${parsed.sender}`
179
+ );
180
+ }
181
+ const newConnection = {
182
+ id: parsed.sender,
183
+ lastSentMessageId: _Messenger.contextEvents[this.options.context].length - 1,
184
+ lastReceivedMessageId: -1,
185
+ desync: false
186
+ };
187
+ this.connections[parsed.sender] = newConnection;
188
+ this.log(`new connection added - ${parsed.context}:${parsed.sender}`);
189
+ }
190
+ handleLostEventsRequest(parsed) {
191
+ const lastMessageIdx = parsed.payload.lastReceivedMessageId;
192
+ const missingEvents = _Messenger.contextEvents[this.options.context].slice(
193
+ lastMessageIdx + 1,
194
+ _Messenger.contextEvents[this.options.context].length
195
+ );
196
+ const message = {
197
+ type: "MESSENGER_EVENT_BATCH",
198
+ payload: {
199
+ events: missingEvents.map(
200
+ (event) => this.addTransactionMetadata(event, parsed.sender)
201
+ )
202
+ }
203
+ };
204
+ this.options.sendMessage(this.addTransactionMetadata(message));
205
+ this.log(
206
+ `messages [0 - ${_Messenger.contextEvents[this.options.context].length - 1}] sent to ${parsed.context}:${parsed.sender}`
207
+ );
208
+ }
209
+ handleDisconnectMessage(parsed) {
210
+ delete this.connections[parsed.sender];
211
+ this.log(`disconnected - ${parsed.context}:${parsed.sender}`);
212
+ }
213
+ sendMessage(message) {
214
+ const parsed = typeof message === "string" ? JSON.parse(message) : message;
215
+ _Messenger.contextEvents[this.options.context].push(parsed);
216
+ Object.values(this.connections).forEach(({ id }) => {
217
+ const msg = this.addTransactionMetadata(parsed, id);
218
+ this.options.sendMessage(msg).then(() => {
219
+ this.connections[id].lastSentMessageId = msg.id;
220
+ }).catch(() => {
221
+ this.options.handleFailedMessage?.(msg);
222
+ this.log(
223
+ `message failed: ${msg.context}:${id} - index: ${_Messenger.contextEvents[this.options.context].length}`
224
+ );
225
+ });
226
+ });
227
+ }
228
+ destroy() {
229
+ if (this.beaconInterval) {
230
+ clearInterval(this.beaconInterval);
231
+ }
232
+ this.options.removeListener(this.handleMessage);
233
+ Object.keys(this.connections).forEach((connection) => {
234
+ const event = {
235
+ type: "MESSENGER_DISCONNECT",
236
+ payload: null
237
+ };
238
+ const message = this.addTransactionMetadata(event, connection);
239
+ this.options.sendMessage(message);
240
+ });
241
+ this.log("destroyed");
242
+ }
243
+ static resetEvents() {
244
+ _Messenger.contextEvents = {};
245
+ }
246
+ };
247
+ // Annotate the CommonJS export names for ESM import in node:
248
+ 0 && (module.exports = {
249
+ Messenger
250
+ });
251
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/messenger/src/index.ts"],"sourcesContent":["import uid from \"tiny-uid\";\nimport type {\n BaseEvent,\n Connection,\n DisconnectEvent,\n EventsBatchEvent,\n InternalEvent,\n MessengerEvent,\n MessengerOptions,\n RequestLostEventsEvent,\n Transaction,\n TransactionMetadata,\n} from \"@player-tools/devtools-types\";\n\nconst counters: Record<string, number> = {};\n\n/**\n * Messenger<EventsType>\n *\n * Self-sufficient, lossless communication between instances.\n *\n * @param options\n * @param options.context - context to use for this instance\n * @param options.id - unique id for this instance, will be generated if not provided\n * @param options.beaconIntervalMS - time to wait between beacons in milliseconds, defaults to 1000\n * @param options.debug - if true, will log debug messages to console, defaults to false\n * @param options.messageCallback - callback to handle messages\n * @param options.sendMessage - function to send messages\n * @param options.addListener - function to add a listener\n * @param options.removeListener - function to remove a listener\n * @param options.handleFailedMessage - function to handle failed messages\n * @param option.log - function to handle logging\n * @returns Messenger\n * @example\n * ```typescript\n * const messenger = new Messenger({{\n * context: \"devtools\",\n * target: \"player\",\n * messageCallback: (message) => dispatch(message),\n * sendMessage: (message) =>\n * browser.tabs\n * ? browser.tabs\n * .query({ active: true, currentWindow: true })\n * .then((tabs) => {\n * if (tabs[0].id) {\n * browser.tabs.sendMessage(tabs[0].id, message);\n * }\n * })\n * : browser.runtime.sendMessage(message),\n * addListener: (callback) => {\n * browser.runtime.onMessage.addListener(callback);\n * },\n * removeListener: (callback) => {\n * browser.runtime.onMessage.removeListener(callback);\n * },\n * });\n * ```\n */\nexport class Messenger<T extends BaseEvent<string, unknown>> {\n /** static record of events per context */\n private static contextEvents: Record<\n string,\n Array<BaseEvent<string, unknown>>\n > = {};\n\n /** connections record */\n private connections: Record<string, Connection> = {};\n\n /** beacon interval */\n private beaconInterval: NodeJS.Timeout | null = null;\n\n /** time between beacons milliseconds */\n private beaconIntervalMS: number;\n\n /** callback to handle messages, here for instance binding */\n private handleMessage: (\n message: TransactionMetadata & MessengerEvent<T>\n ) => void;\n\n /** unique id */\n private id: string;\n\n constructor(private options: MessengerOptions<T>) {\n // set defaults:\n this.id = options.id || uid();\n this.beaconIntervalMS = options.beaconIntervalMS || 1000;\n\n // start beacon interval:\n this.beaconInterval = setInterval(\n this.beacon.bind(this),\n this.beaconIntervalMS\n );\n\n // bind message handler:\n this.handleMessage = this._handleMessage.bind(this);\n\n // add listener:\n this.options.addListener(this.handleMessage);\n\n // if events for this context don't exist, create an empty array\n if (!(Messenger.contextEvents[this.options.context] as T[])) {\n (Messenger.contextEvents[this.options.context] as T[]) = [];\n }\n }\n\n private log(message: string) {\n if (this.options.debug) {\n this.options.logger.log(\n `[MESSENGER-${this.id}](${this.options.context}): ${message}`\n );\n }\n }\n\n /** generate a sequential id for each non-internal message */\n private getTransactionID(message: MessengerEvent<T>, target?: string) {\n const internalEvents: Array<InternalEvent<T>[\"type\"]> = [\n \"MESSENGER_BEACON\",\n \"MESSENGER_DISCONNECT\",\n \"MESSENGER_REQUEST_LOST_EVENTS\",\n \"MESSENGER_EVENT_BATCH\",\n ];\n\n if (\n !target ||\n internalEvents.includes(message.type as InternalEvent<T>[\"type\"])\n ) {\n return -1;\n }\n\n if (!counters[target]) {\n counters[target] = 0;\n }\n\n return counters[target]++;\n }\n\n private addTransactionMetadata(\n event: MessengerEvent<T>,\n target?: string\n ): Transaction<T> {\n const metadata = {\n _messenger_: true,\n id: this.getTransactionID(event, target),\n sender: this.id,\n timestamp: Date.now(),\n context: this.options.context,\n ...(target && { target }),\n };\n\n return {\n ...metadata,\n ...event,\n };\n }\n\n /** there is no persistent layer bookkeeping connections,\n * so beacon to inform others of its presence */\n private beacon() {\n this.options.sendMessage(\n this.addTransactionMetadata({\n type: \"MESSENGER_BEACON\",\n payload: null,\n })\n );\n }\n\n private _handleMessage(transaction: Transaction<T>) {\n const parsed: Transaction<T> =\n typeof transaction === \"string\" ? JSON.parse(transaction) : transaction;\n\n const isFromMessenger = parsed._messenger_;\n const isFromSelf = parsed.sender === this.id;\n const isFromSameContext = parsed.context === this.options.context;\n const isTargetingOthers = parsed.target && parsed.target !== this.id;\n const isKnownConnection = this.connections[parsed.sender];\n\n if (\n !isFromMessenger ||\n isFromSelf ||\n isFromSameContext ||\n isTargetingOthers ||\n (isKnownConnection && parsed.type === \"MESSENGER_BEACON\")\n ) {\n return;\n }\n\n const handlers: Record<string, (parsed: Transaction<T>) => void> = {\n MESSENGER_BEACON: this.handleBeaconMessage.bind(this),\n MESSENGER_DISCONNECT: this.handleDisconnectMessage.bind(this),\n MESSENGER_REQUEST_LOST_EVENTS: this.handleLostEventsRequest.bind(this),\n };\n\n const handler = handlers[(parsed as BaseEvent<string, unknown>).type];\n\n if (handler) {\n handler(parsed);\n return;\n }\n\n if (isKnownConnection) {\n const isBatch = parsed.type === \"MESSENGER_EVENT_BATCH\";\n\n // if batch, get the first message id, so we can check for missing messages:\n const transactionID = isBatch\n ? (parsed.payload as EventsBatchEvent<T>[\"payload\"]).events[0].id\n : parsed.id;\n\n const { lastReceivedMessageId, desync } = this.connections[parsed.sender];\n\n // if we already received this message, ignore:\n if (transactionID <= lastReceivedMessageId) {\n return;\n }\n\n // if we missed messages, request them, unless we already did:\n if (!desync && transactionID > lastReceivedMessageId + 1) {\n const message: RequestLostEventsEvent = {\n type: \"MESSENGER_REQUEST_LOST_EVENTS\",\n payload: {\n lastReceivedMessageId,\n },\n };\n\n this.options.sendMessage(this.addTransactionMetadata(message));\n\n this.log(\n `requesting lost messages from ${parsed.context}:${parsed.sender}`\n );\n\n // set desync, so we don't request again:\n this.connections[parsed.sender].desync = true;\n\n // don't process this message, since we requested missing ones:\n return;\n }\n\n if (isBatch) {\n // clear desync flag on event batch:\n this.connections[parsed.sender].desync = false;\n }\n\n // if batch, get the last message id:\n const newLastMessageIdx = isBatch\n ? (parsed.payload as EventsBatchEvent<T>[\"payload\"]).events.slice(-1)[0]\n .id\n : parsed.id;\n\n // update last received message id:\n this.connections[parsed.sender].lastReceivedMessageId = newLastMessageIdx;\n }\n\n this.options.messageCallback(parsed);\n\n this.log(\n `message received: ${(parsed as BaseEvent<string, unknown>).type}`\n );\n }\n\n private handleBeaconMessage(parsed: Transaction<T>) {\n // if we reach here, we assume a new connection and send all events:\n if ((Messenger.contextEvents[this.options.context] as T[]).length > 0) {\n const message: EventsBatchEvent<T> = {\n type: \"MESSENGER_EVENT_BATCH\",\n payload: {\n events: (Messenger.contextEvents[this.options.context] as T[]).map(\n (event) => this.addTransactionMetadata(event, parsed.sender)\n ),\n },\n };\n\n this.options.sendMessage(\n this.addTransactionMetadata(message, parsed.sender)\n );\n\n this.log(\n `messages [0 - ${\n (Messenger.contextEvents[this.options.context] as T[]).length - 1\n }] sent to ${parsed.context}:${parsed.sender}`\n );\n }\n\n const newConnection: Connection = {\n id: parsed.sender,\n lastSentMessageId:\n (Messenger.contextEvents[this.options.context] as T[]).length - 1,\n lastReceivedMessageId: -1,\n desync: false,\n };\n\n this.connections[parsed.sender] = newConnection;\n\n this.log(`new connection added - ${parsed.context}:${parsed.sender}`);\n }\n\n private handleLostEventsRequest(parsed: Transaction<T>) {\n const lastMessageIdx = (parsed.payload as RequestLostEventsEvent[\"payload\"])\n .lastReceivedMessageId;\n\n const missingEvents = (\n Messenger.contextEvents[this.options.context] as T[]\n ).slice(\n lastMessageIdx + 1,\n (Messenger.contextEvents[this.options.context] as T[]).length\n );\n\n const message: EventsBatchEvent<T> = {\n type: \"MESSENGER_EVENT_BATCH\",\n payload: {\n events: missingEvents.map((event) =>\n this.addTransactionMetadata(event, parsed.sender)\n ),\n },\n };\n\n this.options.sendMessage(this.addTransactionMetadata(message));\n\n this.log(\n `messages [0 - ${\n (Messenger.contextEvents[this.options.context] as T[]).length - 1\n }] sent to ${parsed.context}:${parsed.sender}`\n );\n }\n\n private handleDisconnectMessage(\n parsed: TransactionMetadata & MessengerEvent<T>\n ) {\n delete this.connections[parsed.sender];\n\n this.log(`disconnected - ${parsed.context}:${parsed.sender}`);\n }\n\n public sendMessage(message: T | string) {\n const parsed: T =\n typeof message === \"string\" ? JSON.parse(message) : message;\n\n (Messenger.contextEvents[this.options.context] as T[]).push(parsed);\n\n // send to all connections:\n Object.values(this.connections).forEach(({ id }) => {\n const msg = this.addTransactionMetadata(parsed, id);\n\n this.options\n .sendMessage(msg)\n .then(() => {\n this.connections[id].lastSentMessageId = msg.id;\n })\n .catch(() => {\n this.options.handleFailedMessage?.(msg);\n\n this.log(\n `message failed: ${msg.context}:${id} - index: ${\n (Messenger.contextEvents[this.options.context] as T[]).length\n }`\n );\n });\n });\n }\n\n public destroy() {\n if (this.beaconInterval) {\n clearInterval(this.beaconInterval);\n }\n\n this.options.removeListener(this.handleMessage);\n\n Object.keys(this.connections).forEach((connection) => {\n const event: DisconnectEvent = {\n type: \"MESSENGER_DISCONNECT\",\n payload: null,\n };\n const message = this.addTransactionMetadata(event, connection);\n this.options.sendMessage(message);\n });\n\n this.log(\"destroyed\");\n }\n\n static resetEvents() {\n Messenger.contextEvents = {};\n }\n}\n"],"mappings":"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","names":["uid"]}
@@ -0,0 +1,216 @@
1
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/messenger/src/index.ts
2
+ import uid from "tiny-uid";
3
+ var counters = {};
4
+ var Messenger = class _Messenger {
5
+ constructor(options) {
6
+ this.options = options;
7
+ this.id = options.id || uid();
8
+ this.beaconIntervalMS = options.beaconIntervalMS || 1e3;
9
+ this.beaconInterval = setInterval(
10
+ this.beacon.bind(this),
11
+ this.beaconIntervalMS
12
+ );
13
+ this.handleMessage = this._handleMessage.bind(this);
14
+ this.options.addListener(this.handleMessage);
15
+ if (!_Messenger.contextEvents[this.options.context]) {
16
+ _Messenger.contextEvents[this.options.context] = [];
17
+ }
18
+ }
19
+ /** static record of events per context */
20
+ static contextEvents = {};
21
+ /** connections record */
22
+ connections = {};
23
+ /** beacon interval */
24
+ beaconInterval = null;
25
+ /** time between beacons milliseconds */
26
+ beaconIntervalMS;
27
+ /** callback to handle messages, here for instance binding */
28
+ handleMessage;
29
+ /** unique id */
30
+ id;
31
+ log(message) {
32
+ if (this.options.debug) {
33
+ this.options.logger.log(
34
+ `[MESSENGER-${this.id}](${this.options.context}): ${message}`
35
+ );
36
+ }
37
+ }
38
+ /** generate a sequential id for each non-internal message */
39
+ getTransactionID(message, target) {
40
+ const internalEvents = [
41
+ "MESSENGER_BEACON",
42
+ "MESSENGER_DISCONNECT",
43
+ "MESSENGER_REQUEST_LOST_EVENTS",
44
+ "MESSENGER_EVENT_BATCH"
45
+ ];
46
+ if (!target || internalEvents.includes(message.type)) {
47
+ return -1;
48
+ }
49
+ if (!counters[target]) {
50
+ counters[target] = 0;
51
+ }
52
+ return counters[target]++;
53
+ }
54
+ addTransactionMetadata(event, target) {
55
+ const metadata = {
56
+ _messenger_: true,
57
+ id: this.getTransactionID(event, target),
58
+ sender: this.id,
59
+ timestamp: Date.now(),
60
+ context: this.options.context,
61
+ ...target && { target }
62
+ };
63
+ return {
64
+ ...metadata,
65
+ ...event
66
+ };
67
+ }
68
+ /** there is no persistent layer bookkeeping connections,
69
+ * so beacon to inform others of its presence */
70
+ beacon() {
71
+ this.options.sendMessage(
72
+ this.addTransactionMetadata({
73
+ type: "MESSENGER_BEACON",
74
+ payload: null
75
+ })
76
+ );
77
+ }
78
+ _handleMessage(transaction) {
79
+ const parsed = typeof transaction === "string" ? JSON.parse(transaction) : transaction;
80
+ const isFromMessenger = parsed._messenger_;
81
+ const isFromSelf = parsed.sender === this.id;
82
+ const isFromSameContext = parsed.context === this.options.context;
83
+ const isTargetingOthers = parsed.target && parsed.target !== this.id;
84
+ const isKnownConnection = this.connections[parsed.sender];
85
+ if (!isFromMessenger || isFromSelf || isFromSameContext || isTargetingOthers || isKnownConnection && parsed.type === "MESSENGER_BEACON") {
86
+ return;
87
+ }
88
+ const handlers = {
89
+ MESSENGER_BEACON: this.handleBeaconMessage.bind(this),
90
+ MESSENGER_DISCONNECT: this.handleDisconnectMessage.bind(this),
91
+ MESSENGER_REQUEST_LOST_EVENTS: this.handleLostEventsRequest.bind(this)
92
+ };
93
+ const handler = handlers[parsed.type];
94
+ if (handler) {
95
+ handler(parsed);
96
+ return;
97
+ }
98
+ if (isKnownConnection) {
99
+ const isBatch = parsed.type === "MESSENGER_EVENT_BATCH";
100
+ const transactionID = isBatch ? parsed.payload.events[0].id : parsed.id;
101
+ const { lastReceivedMessageId, desync } = this.connections[parsed.sender];
102
+ if (transactionID <= lastReceivedMessageId) {
103
+ return;
104
+ }
105
+ if (!desync && transactionID > lastReceivedMessageId + 1) {
106
+ const message = {
107
+ type: "MESSENGER_REQUEST_LOST_EVENTS",
108
+ payload: {
109
+ lastReceivedMessageId
110
+ }
111
+ };
112
+ this.options.sendMessage(this.addTransactionMetadata(message));
113
+ this.log(
114
+ `requesting lost messages from ${parsed.context}:${parsed.sender}`
115
+ );
116
+ this.connections[parsed.sender].desync = true;
117
+ return;
118
+ }
119
+ if (isBatch) {
120
+ this.connections[parsed.sender].desync = false;
121
+ }
122
+ const newLastMessageIdx = isBatch ? parsed.payload.events.slice(-1)[0].id : parsed.id;
123
+ this.connections[parsed.sender].lastReceivedMessageId = newLastMessageIdx;
124
+ }
125
+ this.options.messageCallback(parsed);
126
+ this.log(
127
+ `message received: ${parsed.type}`
128
+ );
129
+ }
130
+ handleBeaconMessage(parsed) {
131
+ if (_Messenger.contextEvents[this.options.context].length > 0) {
132
+ const message = {
133
+ type: "MESSENGER_EVENT_BATCH",
134
+ payload: {
135
+ events: _Messenger.contextEvents[this.options.context].map(
136
+ (event) => this.addTransactionMetadata(event, parsed.sender)
137
+ )
138
+ }
139
+ };
140
+ this.options.sendMessage(
141
+ this.addTransactionMetadata(message, parsed.sender)
142
+ );
143
+ this.log(
144
+ `messages [0 - ${_Messenger.contextEvents[this.options.context].length - 1}] sent to ${parsed.context}:${parsed.sender}`
145
+ );
146
+ }
147
+ const newConnection = {
148
+ id: parsed.sender,
149
+ lastSentMessageId: _Messenger.contextEvents[this.options.context].length - 1,
150
+ lastReceivedMessageId: -1,
151
+ desync: false
152
+ };
153
+ this.connections[parsed.sender] = newConnection;
154
+ this.log(`new connection added - ${parsed.context}:${parsed.sender}`);
155
+ }
156
+ handleLostEventsRequest(parsed) {
157
+ const lastMessageIdx = parsed.payload.lastReceivedMessageId;
158
+ const missingEvents = _Messenger.contextEvents[this.options.context].slice(
159
+ lastMessageIdx + 1,
160
+ _Messenger.contextEvents[this.options.context].length
161
+ );
162
+ const message = {
163
+ type: "MESSENGER_EVENT_BATCH",
164
+ payload: {
165
+ events: missingEvents.map(
166
+ (event) => this.addTransactionMetadata(event, parsed.sender)
167
+ )
168
+ }
169
+ };
170
+ this.options.sendMessage(this.addTransactionMetadata(message));
171
+ this.log(
172
+ `messages [0 - ${_Messenger.contextEvents[this.options.context].length - 1}] sent to ${parsed.context}:${parsed.sender}`
173
+ );
174
+ }
175
+ handleDisconnectMessage(parsed) {
176
+ delete this.connections[parsed.sender];
177
+ this.log(`disconnected - ${parsed.context}:${parsed.sender}`);
178
+ }
179
+ sendMessage(message) {
180
+ const parsed = typeof message === "string" ? JSON.parse(message) : message;
181
+ _Messenger.contextEvents[this.options.context].push(parsed);
182
+ Object.values(this.connections).forEach(({ id }) => {
183
+ const msg = this.addTransactionMetadata(parsed, id);
184
+ this.options.sendMessage(msg).then(() => {
185
+ this.connections[id].lastSentMessageId = msg.id;
186
+ }).catch(() => {
187
+ this.options.handleFailedMessage?.(msg);
188
+ this.log(
189
+ `message failed: ${msg.context}:${id} - index: ${_Messenger.contextEvents[this.options.context].length}`
190
+ );
191
+ });
192
+ });
193
+ }
194
+ destroy() {
195
+ if (this.beaconInterval) {
196
+ clearInterval(this.beaconInterval);
197
+ }
198
+ this.options.removeListener(this.handleMessage);
199
+ Object.keys(this.connections).forEach((connection) => {
200
+ const event = {
201
+ type: "MESSENGER_DISCONNECT",
202
+ payload: null
203
+ };
204
+ const message = this.addTransactionMetadata(event, connection);
205
+ this.options.sendMessage(message);
206
+ });
207
+ this.log("destroyed");
208
+ }
209
+ static resetEvents() {
210
+ _Messenger.contextEvents = {};
211
+ }
212
+ };
213
+ export {
214
+ Messenger
215
+ };
216
+ //# sourceMappingURL=index.mjs.map