@amplitude/analytics-core 2.38.0 → 2.40.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.
Files changed (89) hide show
  1. package/lib/cjs/core-client.d.ts +9 -1
  2. package/lib/cjs/core-client.d.ts.map +1 -1
  3. package/lib/cjs/core-client.js +15 -5
  4. package/lib/cjs/core-client.js.map +1 -1
  5. package/lib/cjs/diagnostics/uncaught-sdk-errors.d.ts.map +1 -1
  6. package/lib/cjs/diagnostics/uncaught-sdk-errors.js +42 -12
  7. package/lib/cjs/diagnostics/uncaught-sdk-errors.js.map +1 -1
  8. package/lib/cjs/index.d.ts +5 -0
  9. package/lib/cjs/index.d.ts.map +1 -1
  10. package/lib/cjs/index.js +13 -1
  11. package/lib/cjs/index.js.map +1 -1
  12. package/lib/cjs/messenger/background-capture.d.ts +13 -0
  13. package/lib/cjs/messenger/background-capture.d.ts.map +1 -0
  14. package/lib/cjs/messenger/background-capture.js +64 -0
  15. package/lib/cjs/messenger/background-capture.js.map +1 -0
  16. package/lib/cjs/messenger/base-window-messenger.d.ts +100 -0
  17. package/lib/cjs/messenger/base-window-messenger.d.ts.map +1 -0
  18. package/lib/cjs/messenger/base-window-messenger.js +261 -0
  19. package/lib/cjs/messenger/base-window-messenger.js.map +1 -0
  20. package/lib/cjs/messenger/constants.d.ts +6 -0
  21. package/lib/cjs/messenger/constants.d.ts.map +1 -0
  22. package/lib/cjs/messenger/constants.js +15 -0
  23. package/lib/cjs/messenger/constants.js.map +1 -0
  24. package/lib/cjs/messenger/utils.d.ts +12 -0
  25. package/lib/cjs/messenger/utils.d.ts.map +1 -0
  26. package/lib/cjs/messenger/utils.js +48 -0
  27. package/lib/cjs/messenger/utils.js.map +1 -0
  28. package/lib/cjs/observers/network.d.ts.map +1 -1
  29. package/lib/cjs/observers/network.js +58 -39
  30. package/lib/cjs/observers/network.js.map +1 -1
  31. package/lib/cjs/storage/cookie.d.ts +0 -1
  32. package/lib/cjs/storage/cookie.d.ts.map +1 -1
  33. package/lib/cjs/storage/cookie.js +4 -4
  34. package/lib/cjs/storage/cookie.js.map +1 -1
  35. package/lib/cjs/types/client/browser-client.d.ts +33 -0
  36. package/lib/cjs/types/client/browser-client.d.ts.map +1 -1
  37. package/lib/cjs/types/client/browser-client.js.map +1 -1
  38. package/lib/cjs/types/element-interactions.d.ts +0 -1
  39. package/lib/cjs/types/element-interactions.d.ts.map +1 -1
  40. package/lib/cjs/types/element-interactions.js.map +1 -1
  41. package/lib/cjs/utils/safe-stringify.d.ts +4 -0
  42. package/lib/cjs/utils/safe-stringify.d.ts.map +1 -0
  43. package/lib/cjs/utils/safe-stringify.js +9 -0
  44. package/lib/cjs/utils/safe-stringify.js.map +1 -0
  45. package/lib/esm/core-client.d.ts +9 -1
  46. package/lib/esm/core-client.d.ts.map +1 -1
  47. package/lib/esm/core-client.js +16 -6
  48. package/lib/esm/core-client.js.map +1 -1
  49. package/lib/esm/diagnostics/uncaught-sdk-errors.d.ts.map +1 -1
  50. package/lib/esm/diagnostics/uncaught-sdk-errors.js +43 -13
  51. package/lib/esm/diagnostics/uncaught-sdk-errors.js.map +1 -1
  52. package/lib/esm/index.d.ts +5 -0
  53. package/lib/esm/index.d.ts.map +1 -1
  54. package/lib/esm/index.js +4 -0
  55. package/lib/esm/index.js.map +1 -1
  56. package/lib/esm/messenger/background-capture.d.ts +13 -0
  57. package/lib/esm/messenger/background-capture.d.ts.map +1 -0
  58. package/lib/esm/messenger/background-capture.js +60 -0
  59. package/lib/esm/messenger/background-capture.js.map +1 -0
  60. package/lib/esm/messenger/base-window-messenger.d.ts +100 -0
  61. package/lib/esm/messenger/base-window-messenger.d.ts.map +1 -0
  62. package/lib/esm/messenger/base-window-messenger.js +257 -0
  63. package/lib/esm/messenger/base-window-messenger.js.map +1 -0
  64. package/lib/esm/messenger/constants.d.ts +6 -0
  65. package/lib/esm/messenger/constants.d.ts.map +1 -0
  66. package/lib/esm/messenger/constants.js +12 -0
  67. package/lib/esm/messenger/constants.js.map +1 -0
  68. package/lib/esm/messenger/utils.d.ts +12 -0
  69. package/lib/esm/messenger/utils.d.ts.map +1 -0
  70. package/lib/esm/messenger/utils.js +43 -0
  71. package/lib/esm/messenger/utils.js.map +1 -0
  72. package/lib/esm/observers/network.d.ts.map +1 -1
  73. package/lib/esm/observers/network.js +58 -39
  74. package/lib/esm/observers/network.js.map +1 -1
  75. package/lib/esm/storage/cookie.d.ts +0 -1
  76. package/lib/esm/storage/cookie.d.ts.map +1 -1
  77. package/lib/esm/storage/cookie.js +4 -4
  78. package/lib/esm/storage/cookie.js.map +1 -1
  79. package/lib/esm/types/client/browser-client.d.ts +33 -0
  80. package/lib/esm/types/client/browser-client.d.ts.map +1 -1
  81. package/lib/esm/types/client/browser-client.js.map +1 -1
  82. package/lib/esm/types/element-interactions.d.ts +0 -1
  83. package/lib/esm/types/element-interactions.d.ts.map +1 -1
  84. package/lib/esm/types/element-interactions.js.map +1 -1
  85. package/lib/esm/utils/safe-stringify.d.ts +4 -0
  86. package/lib/esm/utils/safe-stringify.d.ts.map +1 -0
  87. package/lib/esm/utils/safe-stringify.js +6 -0
  88. package/lib/esm/utils/safe-stringify.js.map +1 -0
  89. package/package.json +5 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-window-messenger.d.ts","sourceRoot":"","sources":["../../../src/messenger/base-window-messenger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAK1D,KAAK,cAAc,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B,CAAC;AAQF,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;AAEhD;;GAEG;AACH,QAAA,MAAM,eAAe,oCAA8C,CAAC;AAKpE;;;GAGG;AACH,cAAM,mBAAoB,YAAW,SAAS;IAC5C,yDAAyD;IACzD,QAAQ,CAAC,CAAC,eAAe,CAAC,QAAQ;IAElC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAgD;IACtE,gBAAgB,EAAE;QAChB,CAAC,EAAE,EAAE,MAAM,GAAG;YACZ,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;YAC7B,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;SAC7B,CAAC;KACH,CAAM;IACP,OAAO,CAAC,cAAc,CAAoC;IAE1D;;;;;OAKG;IACH,OAAO,CAAC,eAAe,CAA4B;IAEnD;;;OAGG;IACH,OAAO,CAAC,kBAAkB,CAAoC;gBAElD,EAAE,MAAyB,EAAE,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAInE;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,GAAG,CAAA;KAAE,GAAG,cAAc;IAK/D;;;OAGG;IACI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO;;KAAsB,GAAG,OAAO,CAAC,GAAG,CAAC;IAoB1G;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;;OAGG;IACH,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa;IAgB5D;;;;OAIG;IACG,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBhD;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO;IA6DxE;;OAEG;IACH,OAAO;CAiBR;AAcD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,mBAAmB,CAa7F;AAED,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,257 @@
1
+ var _a;
2
+ import { __awaiter, __generator, __values } from "tslib";
3
+ import { getGlobalScope } from '../global-scope';
4
+ import { AMPLITUDE_ORIGIN } from './constants';
5
+ import { asyncLoadScript, generateUniqueId } from './utils';
6
+ /**
7
+ * Brand key used to identify BaseWindowMessenger instances across bundle boundaries.
8
+ */
9
+ var MESSENGER_BRAND = '__AMPLITUDE_MESSENGER_INSTANCE__';
10
+ /** Global scope key where the singleton messenger is stored. */
11
+ var MESSENGER_GLOBAL_KEY = '__AMPLITUDE_MESSENGER__';
12
+ /**
13
+ * BaseWindowMessenger provides generic cross-window communication via postMessage.
14
+ * Singleton access via getOrCreateWindowMessenger() to prevent duplicate instances
15
+ */
16
+ var BaseWindowMessenger = /** @class */ (function () {
17
+ function BaseWindowMessenger(_b) {
18
+ var _c = _b === void 0 ? {} : _b, _d = _c.origin, origin = _d === void 0 ? AMPLITUDE_ORIGIN : _d;
19
+ /** Brand property for cross-bundle instanceof checks. */
20
+ this[_a] = true;
21
+ this.isSetup = false;
22
+ this.messageHandler = null;
23
+ this.requestCallbacks = {};
24
+ this.actionHandlers = new Map();
25
+ /**
26
+ * Messages received for actions that had no registered handler yet.
27
+ * Drained automatically when the corresponding handler is registered via
28
+ * registerActionHandler(), solving startup race conditions between
29
+ * independently-initialized plugins.
30
+ */
31
+ this.pendingMessages = new Map();
32
+ /**
33
+ * Tracks in-flight and completed script loads by URL.
34
+ * Using a map, this prevents duplicate loads before the first resolves.
35
+ */
36
+ this.scriptLoadPromises = new Map();
37
+ this.endpoint = origin;
38
+ }
39
+ /**
40
+ * Send a message to the parent window (window.opener).
41
+ */
42
+ BaseWindowMessenger.prototype.notify = function (message) {
43
+ var _b, _c, _d, _e;
44
+ (_c = (_b = this.logger) === null || _b === void 0 ? void 0 : _b.debug) === null || _c === void 0 ? void 0 : _c.call(_b, 'Message sent: ', JSON.stringify(message));
45
+ (_e = (_d = window.opener) === null || _d === void 0 ? void 0 : _d.postMessage) === null || _e === void 0 ? void 0 : _e.call(_d, message, this.endpoint);
46
+ };
47
+ /**
48
+ * Send an async request to the parent window with a unique ID.
49
+ * Returns a Promise that resolves when the parent responds.
50
+ */
51
+ BaseWindowMessenger.prototype.sendRequest = function (action, args, options) {
52
+ var _this = this;
53
+ if (options === void 0) { options = { timeout: 15000 }; }
54
+ var id = generateUniqueId();
55
+ var request = { id: id, action: action, args: args };
56
+ var promise = new Promise(function (resolve, reject) {
57
+ _this.requestCallbacks[id] = { resolve: resolve, reject: reject };
58
+ _this.notify(request);
59
+ if (options.timeout > 0) {
60
+ setTimeout(function () {
61
+ reject(new Error("".concat(action, " timed out (id: ").concat(id, ")")));
62
+ delete _this.requestCallbacks[id];
63
+ }, options.timeout);
64
+ }
65
+ });
66
+ return promise;
67
+ };
68
+ /**
69
+ * Handle a response to a previous request by resolving its Promise.
70
+ */
71
+ BaseWindowMessenger.prototype.handleResponse = function (response) {
72
+ var _b;
73
+ if (!this.requestCallbacks[response.id]) {
74
+ (_b = this.logger) === null || _b === void 0 ? void 0 : _b.warn("No callback found for request id: ".concat(response.id));
75
+ return;
76
+ }
77
+ this.requestCallbacks[response.id].resolve(response.responseData);
78
+ delete this.requestCallbacks[response.id];
79
+ };
80
+ /**
81
+ * Register a handler for a specific action type.
82
+ * Logs a warning if overwriting an existing handler.
83
+ */
84
+ BaseWindowMessenger.prototype.registerActionHandler = function (action, handler) {
85
+ var e_1, _b;
86
+ var _c, _d;
87
+ if (this.actionHandlers.has(action)) {
88
+ (_d = (_c = this.logger) === null || _c === void 0 ? void 0 : _c.warn) === null || _d === void 0 ? void 0 : _d.call(_c, "Overwriting existing action handler for: ".concat(action));
89
+ }
90
+ this.actionHandlers.set(action, handler);
91
+ // Replay any messages that arrived before this handler was registered
92
+ var queued = this.pendingMessages.get(action);
93
+ if (queued) {
94
+ this.pendingMessages.delete(action);
95
+ try {
96
+ for (var queued_1 = __values(queued), queued_1_1 = queued_1.next(); !queued_1_1.done; queued_1_1 = queued_1.next()) {
97
+ var data = queued_1_1.value;
98
+ handler(data);
99
+ }
100
+ }
101
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
102
+ finally {
103
+ try {
104
+ if (queued_1_1 && !queued_1_1.done && (_b = queued_1.return)) _b.call(queued_1);
105
+ }
106
+ finally { if (e_1) throw e_1.error; }
107
+ }
108
+ }
109
+ };
110
+ /**
111
+ * Load a script once, deduplicating by URL.
112
+ * Safe against concurrent calls — the second call awaits the first's in-flight Promise
113
+ * rather than triggering a duplicate load.
114
+ */
115
+ BaseWindowMessenger.prototype.loadScriptOnce = function (url) {
116
+ return __awaiter(this, void 0, void 0, function () {
117
+ var existing, loadPromise, error_1;
118
+ return __generator(this, function (_b) {
119
+ switch (_b.label) {
120
+ case 0:
121
+ existing = this.scriptLoadPromises.get(url);
122
+ if (existing) {
123
+ return [2 /*return*/, existing];
124
+ }
125
+ loadPromise = asyncLoadScript(url).then(function () {
126
+ // Resolve to void
127
+ });
128
+ this.scriptLoadPromises.set(url, loadPromise);
129
+ _b.label = 1;
130
+ case 1:
131
+ _b.trys.push([1, 3, , 4]);
132
+ return [4 /*yield*/, loadPromise];
133
+ case 2:
134
+ _b.sent();
135
+ return [3 /*break*/, 4];
136
+ case 3:
137
+ error_1 = _b.sent();
138
+ // Remove failed loads so they can be retried
139
+ this.scriptLoadPromises.delete(url);
140
+ throw error_1;
141
+ case 4: return [2 /*return*/];
142
+ }
143
+ });
144
+ });
145
+ };
146
+ /**
147
+ * Set up the message listener. Idempotent — safe to call multiple times.
148
+ * Subclasses should call super.setup() and then register their own action handlers.
149
+ */
150
+ BaseWindowMessenger.prototype.setup = function (_b) {
151
+ var _this = this;
152
+ var _c, _d;
153
+ var _e = _b === void 0 ? {} : _b, logger = _e.logger, endpoint = _e.endpoint;
154
+ if (logger) {
155
+ this.logger = logger;
156
+ }
157
+ // If endpoint is customized, don't override a previously customized endpoint.
158
+ if (endpoint && this.endpoint === AMPLITUDE_ORIGIN) {
159
+ this.endpoint = endpoint;
160
+ }
161
+ // Only attach the message listener once
162
+ if (this.isSetup) {
163
+ return;
164
+ }
165
+ this.isSetup = true;
166
+ (_d = (_c = this.logger) === null || _c === void 0 ? void 0 : _c.debug) === null || _d === void 0 ? void 0 : _d.call(_c, 'Setting up messenger');
167
+ // Attach Event Listener to listen for messages from the parent window
168
+ this.messageHandler = function (event) {
169
+ var _b, _c, _d, _e, _f;
170
+ (_c = (_b = _this.logger) === null || _b === void 0 ? void 0 : _b.debug) === null || _c === void 0 ? void 0 : _c.call(_b, 'Message received: ', JSON.stringify(event));
171
+ // Only accept messages from the specified origin
172
+ if (_this.endpoint !== event.origin) {
173
+ return;
174
+ }
175
+ var eventData = event.data;
176
+ var action = eventData === null || eventData === void 0 ? void 0 : eventData.action;
177
+ // Ignore messages without action
178
+ if (!action) {
179
+ return;
180
+ }
181
+ // If id exists, handle responses to previous requests
182
+ if ('id' in eventData && eventData.id) {
183
+ (_e = (_d = _this.logger) === null || _d === void 0 ? void 0 : _d.debug) === null || _e === void 0 ? void 0 : _e.call(_d, 'Received Response to previous request: ', JSON.stringify(event));
184
+ _this.handleResponse(eventData);
185
+ }
186
+ else {
187
+ if (action === 'ping') {
188
+ _this.notify({ action: 'pong' });
189
+ return;
190
+ }
191
+ // Dispatch to registered action handlers, or buffer for late registration
192
+ var handler = _this.actionHandlers.get(action);
193
+ if (handler) {
194
+ handler(eventData.data);
195
+ }
196
+ else {
197
+ var queue = (_f = _this.pendingMessages.get(action)) !== null && _f !== void 0 ? _f : [];
198
+ queue.push(eventData.data);
199
+ _this.pendingMessages.set(action, queue);
200
+ }
201
+ }
202
+ };
203
+ window.addEventListener('message', this.messageHandler);
204
+ this.notify({ action: 'page-loaded' });
205
+ };
206
+ /**
207
+ * Tear down the messenger: remove the message listener, clear all state.
208
+ */
209
+ BaseWindowMessenger.prototype.destroy = function () {
210
+ if (this.messageHandler) {
211
+ window.removeEventListener('message', this.messageHandler);
212
+ this.messageHandler = null;
213
+ }
214
+ this.isSetup = false;
215
+ this.actionHandlers.clear();
216
+ this.pendingMessages.clear();
217
+ this.requestCallbacks = {};
218
+ this.scriptLoadPromises.clear();
219
+ // Remove from global scope if this is the singleton
220
+ var globalScope = getGlobalScope();
221
+ if ((globalScope === null || globalScope === void 0 ? void 0 : globalScope[MESSENGER_GLOBAL_KEY]) === this) {
222
+ delete globalScope[MESSENGER_GLOBAL_KEY];
223
+ }
224
+ };
225
+ return BaseWindowMessenger;
226
+ }());
227
+ _a = MESSENGER_BRAND;
228
+ /**
229
+ * Type guard: checks whether a value is a BaseWindowMessenger instance.
230
+ */
231
+ function isWindowMessenger(value) {
232
+ return (typeof value === 'object' &&
233
+ value !== null &&
234
+ MESSENGER_BRAND in value &&
235
+ value[MESSENGER_BRAND] === true);
236
+ }
237
+ /**
238
+ * Get or create a singleton BaseWindowMessenger instance.
239
+ * Ensures only one messenger (and one message listener) exists per page,
240
+ * preventing duplicate script loads and double notifications.
241
+ *
242
+ * The singleton is stored on globalScope under the same MESSENGER_KEY.
243
+ * The branded property check verifies the stored value is actually a messenger.
244
+ */
245
+ export function getOrCreateWindowMessenger(options) {
246
+ var globalScope = getGlobalScope();
247
+ var existing = globalScope === null || globalScope === void 0 ? void 0 : globalScope[MESSENGER_GLOBAL_KEY];
248
+ if (isWindowMessenger(existing)) {
249
+ return existing;
250
+ }
251
+ var messenger = new BaseWindowMessenger(options);
252
+ if (globalScope) {
253
+ globalScope[MESSENGER_GLOBAL_KEY] = messenger;
254
+ }
255
+ return messenger;
256
+ }
257
+ //# sourceMappingURL=base-window-messenger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-window-messenger.js","sourceRoot":"","sources":["../../../src/messenger/base-window-messenger.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-restricted-globals */\nimport { ILogger } from '../logger';\nimport { Messenger } from '../types/element-interactions';\nimport { getGlobalScope } from '../global-scope';\nimport { AMPLITUDE_ORIGIN } from './constants';\nimport { asyncLoadScript, generateUniqueId } from './utils';\n\ntype MessageRequest = {\n id: string;\n action: string;\n args: Record<string, any>;\n};\n\ntype MessageResponse = {\n id: string;\n action: string;\n responseData: any;\n};\n\nexport type ActionHandler = (data: any) => void;\n\n/**\n * Brand key used to identify BaseWindowMessenger instances across bundle boundaries.\n */\nconst MESSENGER_BRAND = '__AMPLITUDE_MESSENGER_INSTANCE__' as const;\n\n/** Global scope key where the singleton messenger is stored. */\nconst MESSENGER_GLOBAL_KEY = '__AMPLITUDE_MESSENGER__';\n\n/**\n * BaseWindowMessenger provides generic cross-window communication via postMessage.\n * Singleton access via getOrCreateWindowMessenger() to prevent duplicate instances\n */\nclass BaseWindowMessenger implements Messenger {\n /** Brand property for cross-bundle instanceof checks. */\n readonly [MESSENGER_BRAND] = true;\n\n endpoint: string;\n logger?: ILogger;\n private isSetup = false;\n private messageHandler: ((event: MessageEvent) => void) | null = null;\n requestCallbacks: {\n [id: string]: {\n resolve: (data: any) => void;\n reject: (data: any) => void;\n };\n } = {};\n private actionHandlers = new Map<string, ActionHandler>();\n\n /**\n * Messages received for actions that had no registered handler yet.\n * Drained automatically when the corresponding handler is registered via\n * registerActionHandler(), solving startup race conditions between\n * independently-initialized plugins.\n */\n private pendingMessages = new Map<string, any[]>();\n\n /**\n * Tracks in-flight and completed script loads by URL.\n * Using a map, this prevents duplicate loads before the first resolves.\n */\n private scriptLoadPromises = new Map<string, Promise<void>>();\n\n constructor({ origin = AMPLITUDE_ORIGIN }: { origin?: string } = {}) {\n this.endpoint = origin;\n }\n\n /**\n * Send a message to the parent window (window.opener).\n */\n notify(message: { action: string; data?: any } | MessageRequest) {\n this.logger?.debug?.('Message sent: ', JSON.stringify(message));\n (window.opener as WindowProxy)?.postMessage?.(message, this.endpoint);\n }\n\n /**\n * Send an async request to the parent window with a unique ID.\n * Returns a Promise that resolves when the parent responds.\n */\n public sendRequest(action: string, args: Record<string, any>, options = { timeout: 15_000 }): Promise<any> {\n const id = generateUniqueId();\n const request: MessageRequest = { id, action, args };\n\n const promise = new Promise((resolve, reject) => {\n this.requestCallbacks[id] = { resolve, reject };\n\n this.notify(request);\n\n if (options.timeout > 0) {\n setTimeout(() => {\n reject(new Error(`${action} timed out (id: ${id})`));\n delete this.requestCallbacks[id];\n }, options.timeout);\n }\n });\n\n return promise;\n }\n\n /**\n * Handle a response to a previous request by resolving its Promise.\n */\n private handleResponse(response: MessageResponse) {\n if (!this.requestCallbacks[response.id]) {\n this.logger?.warn(`No callback found for request id: ${response.id}`);\n return;\n }\n\n this.requestCallbacks[response.id].resolve(response.responseData);\n delete this.requestCallbacks[response.id];\n }\n\n /**\n * Register a handler for a specific action type.\n * Logs a warning if overwriting an existing handler.\n */\n registerActionHandler(action: string, handler: ActionHandler) {\n if (this.actionHandlers.has(action)) {\n this.logger?.warn?.(`Overwriting existing action handler for: ${action}`);\n }\n this.actionHandlers.set(action, handler);\n\n // Replay any messages that arrived before this handler was registered\n const queued = this.pendingMessages.get(action);\n if (queued) {\n this.pendingMessages.delete(action);\n for (const data of queued) {\n handler(data);\n }\n }\n }\n\n /**\n * Load a script once, deduplicating by URL.\n * Safe against concurrent calls — the second call awaits the first's in-flight Promise\n * rather than triggering a duplicate load.\n */\n async loadScriptOnce(url: string): Promise<void> {\n const existing = this.scriptLoadPromises.get(url);\n if (existing) {\n return existing;\n }\n\n const loadPromise = asyncLoadScript(url).then(() => {\n // Resolve to void\n });\n this.scriptLoadPromises.set(url, loadPromise);\n\n try {\n await loadPromise;\n } catch (error) {\n // Remove failed loads so they can be retried\n this.scriptLoadPromises.delete(url);\n throw error;\n }\n }\n\n /**\n * Set up the message listener. Idempotent — safe to call multiple times.\n * Subclasses should call super.setup() and then register their own action handlers.\n */\n setup({ logger, endpoint }: { logger?: ILogger; endpoint?: string } = {}) {\n if (logger) {\n this.logger = logger;\n }\n\n // If endpoint is customized, don't override a previously customized endpoint.\n if (endpoint && this.endpoint === AMPLITUDE_ORIGIN) {\n this.endpoint = endpoint;\n }\n\n // Only attach the message listener once\n if (this.isSetup) {\n return;\n }\n this.isSetup = true;\n\n this.logger?.debug?.('Setting up messenger');\n\n // Attach Event Listener to listen for messages from the parent window\n this.messageHandler = (event: MessageEvent) => {\n this.logger?.debug?.('Message received: ', JSON.stringify(event));\n\n // Only accept messages from the specified origin\n if (this.endpoint !== event.origin) {\n return;\n }\n\n const eventData = event.data as { action?: string; id?: string; data?: any; responseData?: any };\n const action = eventData?.action;\n\n // Ignore messages without action\n if (!action) {\n return;\n }\n\n // If id exists, handle responses to previous requests\n if ('id' in eventData && eventData.id) {\n this.logger?.debug?.('Received Response to previous request: ', JSON.stringify(event));\n this.handleResponse(eventData as MessageResponse);\n } else {\n if (action === 'ping') {\n this.notify({ action: 'pong' });\n return;\n }\n\n // Dispatch to registered action handlers, or buffer for late registration\n const handler = this.actionHandlers.get(action);\n if (handler) {\n handler(eventData.data);\n } else {\n const queue = this.pendingMessages.get(action) ?? [];\n queue.push(eventData.data);\n this.pendingMessages.set(action, queue);\n }\n }\n };\n window.addEventListener('message', this.messageHandler);\n\n this.notify({ action: 'page-loaded' });\n }\n\n /**\n * Tear down the messenger: remove the message listener, clear all state.\n */\n destroy() {\n if (this.messageHandler) {\n window.removeEventListener('message', this.messageHandler);\n this.messageHandler = null;\n }\n this.isSetup = false;\n this.actionHandlers.clear();\n this.pendingMessages.clear();\n this.requestCallbacks = {};\n this.scriptLoadPromises.clear();\n\n // Remove from global scope if this is the singleton\n const globalScope = getGlobalScope() as Record<string, unknown> | undefined;\n if (globalScope?.[MESSENGER_GLOBAL_KEY] === this) {\n delete globalScope[MESSENGER_GLOBAL_KEY];\n }\n }\n}\n\n/**\n * Type guard: checks whether a value is a BaseWindowMessenger instance.\n */\nfunction isWindowMessenger(value: unknown): value is BaseWindowMessenger {\n return (\n typeof value === 'object' &&\n value !== null &&\n MESSENGER_BRAND in value &&\n (value as Record<string, unknown>)[MESSENGER_BRAND] === true\n );\n}\n\n/**\n * Get or create a singleton BaseWindowMessenger instance.\n * Ensures only one messenger (and one message listener) exists per page,\n * preventing duplicate script loads and double notifications.\n *\n * The singleton is stored on globalScope under the same MESSENGER_KEY.\n * The branded property check verifies the stored value is actually a messenger.\n */\nexport function getOrCreateWindowMessenger(options?: { origin?: string }): BaseWindowMessenger {\n const globalScope = getGlobalScope() as Record<string, unknown> | undefined;\n\n const existing = globalScope?.[MESSENGER_GLOBAL_KEY];\n if (isWindowMessenger(existing)) {\n return existing;\n }\n\n const messenger = new BaseWindowMessenger(options);\n if (globalScope) {\n globalScope[MESSENGER_GLOBAL_KEY] = messenger;\n }\n return messenger;\n}\n\nexport type { BaseWindowMessenger };\n"]}
@@ -0,0 +1,6 @@
1
+ export declare const AMPLITUDE_ORIGIN = "https://app.amplitude.com";
2
+ export declare const AMPLITUDE_ORIGIN_EU = "https://app.eu.amplitude.com";
3
+ export declare const AMPLITUDE_ORIGIN_STAGING = "https://apps.stag2.amplitude.com";
4
+ export declare const AMPLITUDE_ORIGINS_MAP: Record<string, string>;
5
+ export declare const AMPLITUDE_BACKGROUND_CAPTURE_SCRIPT_URL = "https://cdn.amplitude.com/libs/background-capture-1.0.0-alpha.1.js.gz";
6
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/messenger/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAC5D,eAAO,MAAM,mBAAmB,iCAAiC,CAAC;AAClE,eAAO,MAAM,wBAAwB,qCAAqC,CAAC;AAC3E,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAIxD,CAAC;AAGF,eAAO,MAAM,uCAAuC,0EACqB,CAAC"}
@@ -0,0 +1,12 @@
1
+ // Shared origin constants for Amplitude cross-window communication
2
+ export var AMPLITUDE_ORIGIN = 'https://app.amplitude.com';
3
+ export var AMPLITUDE_ORIGIN_EU = 'https://app.eu.amplitude.com';
4
+ export var AMPLITUDE_ORIGIN_STAGING = 'https://apps.stag2.amplitude.com';
5
+ export var AMPLITUDE_ORIGINS_MAP = {
6
+ US: AMPLITUDE_ORIGIN,
7
+ EU: AMPLITUDE_ORIGIN_EU,
8
+ STAGING: AMPLITUDE_ORIGIN_STAGING,
9
+ };
10
+ // Background capture script URL (shared between autocapture and session-replay)
11
+ export var AMPLITUDE_BACKGROUND_CAPTURE_SCRIPT_URL = 'https://cdn.amplitude.com/libs/background-capture-1.0.0-alpha.1.js.gz';
12
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/messenger/constants.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,MAAM,CAAC,IAAM,gBAAgB,GAAG,2BAA2B,CAAC;AAC5D,MAAM,CAAC,IAAM,mBAAmB,GAAG,8BAA8B,CAAC;AAClE,MAAM,CAAC,IAAM,wBAAwB,GAAG,kCAAkC,CAAC;AAC3E,MAAM,CAAC,IAAM,qBAAqB,GAA2B;IAC3D,EAAE,EAAE,gBAAgB;IACpB,EAAE,EAAE,mBAAmB;IACvB,OAAO,EAAE,wBAAwB;CAClC,CAAC;AAEF,gFAAgF;AAChF,MAAM,CAAC,IAAM,uCAAuC,GAClD,uEAAuE,CAAC","sourcesContent":["// Shared origin constants for Amplitude cross-window communication\nexport const AMPLITUDE_ORIGIN = 'https://app.amplitude.com';\nexport const AMPLITUDE_ORIGIN_EU = 'https://app.eu.amplitude.com';\nexport const AMPLITUDE_ORIGIN_STAGING = 'https://apps.stag2.amplitude.com';\nexport const AMPLITUDE_ORIGINS_MAP: Record<string, string> = {\n US: AMPLITUDE_ORIGIN,\n EU: AMPLITUDE_ORIGIN_EU,\n STAGING: AMPLITUDE_ORIGIN_STAGING,\n};\n\n// Background capture script URL (shared between autocapture and session-replay)\nexport const AMPLITUDE_BACKGROUND_CAPTURE_SCRIPT_URL =\n 'https://cdn.amplitude.com/libs/background-capture-1.0.0-alpha.1.js.gz';\n"]}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Dynamically loads an external script by appending a <script> tag to the document head.
3
+ * Deduplicates by checking if a script with the same src already exists.
4
+ */
5
+ export declare const asyncLoadScript: (url: string) => Promise<{
6
+ status: boolean;
7
+ }>;
8
+ /**
9
+ * Generates a simple unique ID for message request/response correlation.
10
+ */
11
+ export declare function generateUniqueId(): string;
12
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/messenger/utils.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,eAAe,QAAS,MAAM,KAAG,QAAQ;IAAE,QAAQ,OAAO,CAAA;CAAE,CAiCxE,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC"}
@@ -0,0 +1,43 @@
1
+ /* eslint-disable no-restricted-globals */
2
+ /**
3
+ * Dynamically loads an external script by appending a <script> tag to the document head.
4
+ * Deduplicates by checking if a script with the same src already exists.
5
+ */
6
+ export var asyncLoadScript = function (url) {
7
+ // Dedup: if a script with this src already exists, resolve immediately
8
+ var existing = document.querySelector("script[src=\"".concat(CSS.escape(url), "\"]"));
9
+ if (existing) {
10
+ return Promise.resolve({ status: true });
11
+ }
12
+ return new Promise(function (resolve, reject) {
13
+ var _a;
14
+ try {
15
+ var scriptElement = document.createElement('script');
16
+ scriptElement.type = 'text/javascript';
17
+ scriptElement.async = true;
18
+ scriptElement.src = url;
19
+ scriptElement.addEventListener('load', function () {
20
+ resolve({ status: true });
21
+ }, { once: true });
22
+ scriptElement.addEventListener('error', function () {
23
+ reject({
24
+ status: false,
25
+ message: "Failed to load the script ".concat(url),
26
+ });
27
+ });
28
+ /* istanbul ignore next */
29
+ (_a = document.head) === null || _a === void 0 ? void 0 : _a.appendChild(scriptElement);
30
+ }
31
+ catch (error) {
32
+ /* istanbul ignore next */
33
+ reject(error);
34
+ }
35
+ });
36
+ };
37
+ /**
38
+ * Generates a simple unique ID for message request/response correlation.
39
+ */
40
+ export function generateUniqueId() {
41
+ return "".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
42
+ }
43
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/messenger/utils.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAE1C;;;GAGG;AACH,MAAM,CAAC,IAAM,eAAe,GAAG,UAAC,GAAW;IACzC,uEAAuE;IACvE,IAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,uBAAe,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,QAAI,CAAC,CAAC;IAC5E,IAAI,QAAQ,EAAE;QACZ,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;KAC1C;IAED,OAAO,IAAI,OAAO,CAAC,UAAC,OAAO,EAAE,MAAM;;QACjC,IAAI;YACF,IAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACvD,aAAa,CAAC,IAAI,GAAG,iBAAiB,CAAC;YACvC,aAAa,CAAC,KAAK,GAAG,IAAI,CAAC;YAC3B,aAAa,CAAC,GAAG,GAAG,GAAG,CAAC;YACxB,aAAa,CAAC,gBAAgB,CAC5B,MAAM,EACN;gBACE,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5B,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;YACF,aAAa,CAAC,gBAAgB,CAAC,OAAO,EAAE;gBACtC,MAAM,CAAC;oBACL,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE,oCAA6B,GAAG,CAAE;iBAC5C,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YACH,0BAA0B;YAC1B,MAAA,QAAQ,CAAC,IAAI,0CAAE,WAAW,CAAC,aAAa,CAAC,CAAC;SAC3C;QAAC,OAAO,KAAK,EAAE;YACd,0BAA0B;YAC1B,MAAM,CAAC,KAAK,CAAC,CAAC;SACf;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,UAAG,IAAI,CAAC,GAAG,EAAE,cAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,CAAC;AACpE,CAAC","sourcesContent":["/* eslint-disable no-restricted-globals */\n\n/**\n * Dynamically loads an external script by appending a <script> tag to the document head.\n * Deduplicates by checking if a script with the same src already exists.\n */\nexport const asyncLoadScript = (url: string): Promise<{ status: boolean }> => {\n // Dedup: if a script with this src already exists, resolve immediately\n const existing = document.querySelector(`script[src=\"${CSS.escape(url)}\"]`);\n if (existing) {\n return Promise.resolve({ status: true });\n }\n\n return new Promise((resolve, reject) => {\n try {\n const scriptElement = document.createElement('script');\n scriptElement.type = 'text/javascript';\n scriptElement.async = true;\n scriptElement.src = url;\n scriptElement.addEventListener(\n 'load',\n () => {\n resolve({ status: true });\n },\n { once: true },\n );\n scriptElement.addEventListener('error', () => {\n reject({\n status: false,\n message: `Failed to load the script ${url}`,\n });\n });\n /* istanbul ignore next */\n document.head?.appendChild(scriptElement);\n } catch (error) {\n /* istanbul ignore next */\n reject(error);\n }\n });\n};\n\n/**\n * Generates a simple unique ID for message request/response correlation.\n */\nexport function generateUniqueId(): string {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../../src/observers/network.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,eAAe,EACf,mBAAmB,EAKnB,gBAAgB,EAGjB,MAAM,0BAA0B,CAAC;AAoBlC,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAE1E,qBAAa,oBAAoB;aACH,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI;aAAkB,EAAE,EAAE,MAAM;gBAA1E,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,EAAkB,EAAE,GAAE,MAAe;CAChH;AAED,KAAK,mBAAmB,GAAG;IACzB,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC;IAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC;AAgBF,qBAAa,eAAe;IAC1B,OAAO,CAAC,cAAc,CAAgD;IAEtE,OAAO,CAAC,WAAW,CAAC,CAAoB;IACxC,OAAO,CAAC,MAAM,CAAC,CAAU;IACzB,OAAO,CAAC,WAAW,CAAS;gBAChB,MAAM,CAAC,EAAE,OAAO;IAU5B,MAAM,CAAC,WAAW,IAAI,OAAO;IAK7B,SAAS,CAAC,aAAa,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,OAAO;IA+B/D,WAAW,CAAC,aAAa,EAAE,oBAAoB;IAI/C,SAAS,CAAC,qBAAqB,CAAC,KAAK,EAAE,mBAAmB;IAa1D,yBAAyB,CACvB,WAAW,EAAE,OAAO,GAAG,KAAK,EAC5B,WAAW,EAAE,WAAW,GAAG,GAAG,GAAG,mBAAmB,GAAG,SAAS,EAChE,cAAc,EAAE,eAAe,GAAG,SAAS,EAC3C,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,UAAU,EAAE,KAAK,GAAG,SAAS,EAC7B,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,MAAM;IA+DxB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,YAAY;IA8DpB;;;;;;;;;OASG;IACH,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe;IA8B9E,OAAO,CAAC,UAAU;CAqHnB;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
1
+ {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../../src/observers/network.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,eAAe,EACf,mBAAmB,EAKnB,gBAAgB,EAGjB,MAAM,0BAA0B,CAAC;AAoBlC,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAE1E,qBAAa,oBAAoB;aACH,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI;aAAkB,EAAE,EAAE,MAAM;gBAA1E,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,EAAkB,EAAE,GAAE,MAAe;CAChH;AAED,KAAK,mBAAmB,GAAG;IACzB,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC;IAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC;AAwBF,qBAAa,eAAe;IAC1B,OAAO,CAAC,cAAc,CAAgD;IAEtE,OAAO,CAAC,WAAW,CAAC,CAAoB;IACxC,OAAO,CAAC,MAAM,CAAC,CAAU;IACzB,OAAO,CAAC,WAAW,CAAS;gBAChB,MAAM,CAAC,EAAE,OAAO;IAU5B,MAAM,CAAC,WAAW,IAAI,OAAO;IAK7B,SAAS,CAAC,aAAa,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,OAAO;IA+B/D,WAAW,CAAC,aAAa,EAAE,oBAAoB;IAI/C,SAAS,CAAC,qBAAqB,CAAC,KAAK,EAAE,mBAAmB;IAe1D,yBAAyB,CACvB,WAAW,EAAE,OAAO,GAAG,KAAK,EAC5B,WAAW,EAAE,WAAW,GAAG,GAAG,GAAG,mBAAmB,GAAG,SAAS,EAChE,cAAc,EAAE,eAAe,GAAG,SAAS,EAC3C,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,UAAU,EAAE,KAAK,GAAG,SAAS,EAC7B,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,MAAM;IA+DxB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,YAAY;IA8DpB;;;;;;;;;OASG;IACH,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe;IAgC9E,OAAO,CAAC,UAAU;CAmInB;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
@@ -17,6 +17,14 @@ var NetworkEventCallback = /** @class */ (function () {
17
17
  return NetworkEventCallback;
18
18
  }());
19
19
  export { NetworkEventCallback };
20
+ function safeInvoke(fn) {
21
+ try {
22
+ fn();
23
+ }
24
+ catch (err) {
25
+ // swallow the error
26
+ }
27
+ }
20
28
  var NetworkObserver = /** @class */ (function () {
21
29
  function NetworkObserver(logger) {
22
30
  this.eventCallbacks = new Map();
@@ -68,15 +76,17 @@ var NetworkObserver = /** @class */ (function () {
68
76
  NetworkObserver.prototype.triggerEventCallbacks = function (event) {
69
77
  var _this = this;
70
78
  this.eventCallbacks.forEach(function (callback) {
71
- var _a;
72
79
  try {
73
80
  callback.callback(event);
74
81
  }
75
82
  catch (err) {
76
83
  // if the callback throws an error, we should catch it
77
84
  // to avoid breaking the fetch promise chain
78
- /* istanbul ignore next */
79
- (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while triggering event callbacks', err);
85
+ safeInvoke(function () {
86
+ var _a;
87
+ /* istanbul ignore next */
88
+ (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while triggering event callbacks', err);
89
+ });
80
90
  }
81
91
  });
82
92
  };
@@ -148,26 +158,26 @@ var NetworkObserver = /** @class */ (function () {
148
158
  */
149
159
  this.globalScope.fetch = function (requestInfo, requestInit) { return __awaiter(_this, void 0, void 0, function () {
150
160
  var timestamps, originalResponse, originalError, err_1;
151
- var _a, _b;
152
- return __generator(this, function (_c) {
153
- switch (_c.label) {
161
+ var _this = this;
162
+ return __generator(this, function (_a) {
163
+ switch (_a.label) {
154
164
  case 0:
155
165
  try {
156
166
  timestamps = this.getTimestamps();
157
167
  }
158
168
  catch (error) {
159
169
  /* istanbul ignore next */
160
- (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while retrieving timestamps', error);
170
+ safeInvoke(function () { var _a; return (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while retrieving timestamps', error); });
161
171
  }
162
- _c.label = 1;
172
+ _a.label = 1;
163
173
  case 1:
164
- _c.trys.push([1, 3, , 4]);
174
+ _a.trys.push([1, 3, , 4]);
165
175
  return [4 /*yield*/, originalFetch(requestInfo, requestInit)];
166
176
  case 2:
167
- originalResponse = _c.sent();
177
+ originalResponse = _a.sent();
168
178
  return [3 /*break*/, 4];
169
179
  case 3:
170
- err_1 = _c.sent();
180
+ err_1 = _a.sent();
171
181
  // Capture error information
172
182
  originalError = err_1;
173
183
  return [3 /*break*/, 4];
@@ -184,7 +194,7 @@ var NetworkObserver = /** @class */ (function () {
184
194
  // this catch shouldn't be reachable, but keep it here for safety
185
195
  // because we're overriding the fetch function and better to be safe than sorry
186
196
  /* istanbul ignore next */
187
- (_b = this.logger) === null || _b === void 0 ? void 0 : _b.debug('an unexpected error occurred while handling fetch', err);
197
+ safeInvoke(function () { var _a; return (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while handling fetch', err); });
188
198
  }
189
199
  // 4. return the original response or throw the original error
190
200
  if (originalResponse) {
@@ -211,7 +221,7 @@ var NetworkObserver = /** @class */ (function () {
211
221
  */
212
222
  NetworkObserver.createXhrJsonParser = function (xhrUnsafe, context) {
213
223
  return function () {
214
- var _a, _b;
224
+ var _a;
215
225
  try {
216
226
  if (xhrUnsafe.responseType === 'json') {
217
227
  // if response is a JS object, clone it so that subscribers can't mutate it
@@ -231,7 +241,10 @@ var NetworkObserver = /** @class */ (function () {
231
241
  if (err instanceof Error && err.name === 'InvalidStateError') {
232
242
  // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText#exceptions
233
243
  // if we reach here, it means we don't handle responseType correctly
234
- (_b = context.logger) === null || _b === void 0 ? void 0 : _b.error("unexpected error when retrieving responseText. responseType='".concat(xhrUnsafe.responseType, "'"));
244
+ safeInvoke(function () {
245
+ var _a;
246
+ return (_a = context.logger) === null || _a === void 0 ? void 0 : _a.debug("unexpected error when retrieving responseText. responseType='".concat(xhrUnsafe.responseType, "'"));
247
+ });
235
248
  }
236
249
  // the other possible error is Json Parse error which we fail silently
237
250
  return null;
@@ -253,20 +266,20 @@ var NetworkObserver = /** @class */ (function () {
253
266
  * and make sure another developer who is an expert reviews this change throughly
254
267
  */
255
268
  xhrProto.open = function () {
256
- var _a, _b;
269
+ var _a;
257
270
  var args = [];
258
271
  for (var _i = 0; _i < arguments.length; _i++) {
259
272
  args[_i] = arguments[_i];
260
273
  }
261
274
  var xhrSafe = this;
262
- var _c = __read(args, 2), method = _c[0], url = _c[1];
275
+ var _b = __read(args, 2), method = _b[0], url = _b[1];
263
276
  try {
264
277
  /* istanbul ignore next */
265
278
  xhrSafe.$$AmplitudeAnalyticsEvent = __assign({ method: method, url: (_a = url === null || url === void 0 ? void 0 : url.toString) === null || _a === void 0 ? void 0 : _a.call(url), headers: {} }, networkObserverContext.getTimestamps());
266
279
  }
267
280
  catch (err) {
268
281
  /* istanbul ignore next */
269
- (_b = networkObserverContext.logger) === null || _b === void 0 ? void 0 : _b.error('an unexpected error occurred while calling xhr open', err);
282
+ safeInvoke(function () { var _a; return (_a = networkObserverContext.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while calling xhr open', err); });
270
283
  }
271
284
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
272
285
  return originalXhrOpen.apply(xhrSafe, args);
@@ -290,24 +303,28 @@ var NetworkObserver = /** @class */ (function () {
290
303
  var getJson = NetworkObserver.createXhrJsonParser(xhrUnsafe, networkObserverContext);
291
304
  var body = args[0];
292
305
  var requestEvent = xhrSafe.$$AmplitudeAnalyticsEvent;
293
- xhrSafe.addEventListener('loadend', function () {
294
- var _a;
295
- try {
296
- var responseHeaders = xhrSafe.getAllResponseHeaders();
297
- var responseBodySize = xhrSafe.getResponseHeader('content-length');
298
- var responseWrapper = new ResponseWrapperXhr(xhrSafe.status, responseHeaders,
299
- /* istanbul ignore next */
300
- responseBodySize ? parseInt(responseBodySize, 10) : undefined, getJson);
301
- var requestHeaders = xhrSafe.$$AmplitudeAnalyticsEvent.headers;
302
- var requestWrapper = new RequestWrapperXhr(body, requestHeaders);
303
- requestEvent.status = xhrSafe.status;
304
- networkObserverContext.handleNetworkRequestEvent('xhr', { url: requestEvent.url, method: requestEvent.method }, requestWrapper, responseWrapper, undefined, requestEvent.startTime, requestEvent.durationStart);
305
- }
306
- catch (err) {
307
- /* istanbul ignore next */
308
- (_a = networkObserverContext.logger) === null || _a === void 0 ? void 0 : _a.error('an unexpected error occurred while handling xhr send', err);
309
- }
310
- });
306
+ // if xhrSafe.$$AmplitudeAnalyticsEvent is not set, it means that
307
+ // the xhr.open method was called before we monkey-patched XHR and
308
+ // the event is missed
309
+ if (xhrSafe.$$AmplitudeAnalyticsEvent) {
310
+ xhrSafe.addEventListener('loadend', function () {
311
+ try {
312
+ var responseHeaders = xhrSafe.getAllResponseHeaders();
313
+ var responseBodySize = xhrSafe.getResponseHeader('content-length');
314
+ var responseWrapper = new ResponseWrapperXhr(xhrSafe.status, responseHeaders,
315
+ /* istanbul ignore next */
316
+ responseBodySize ? parseInt(responseBodySize, 10) : undefined, getJson);
317
+ var requestHeaders = xhrSafe.$$AmplitudeAnalyticsEvent.headers;
318
+ var requestWrapper = new RequestWrapperXhr(body, requestHeaders);
319
+ requestEvent.status = xhrSafe.status;
320
+ networkObserverContext.handleNetworkRequestEvent('xhr', { url: requestEvent.url, method: requestEvent.method }, requestWrapper, responseWrapper, undefined, requestEvent.startTime, requestEvent.durationStart);
321
+ }
322
+ catch (err) {
323
+ /* istanbul ignore next */
324
+ safeInvoke(function () { var _a; return (_a = networkObserverContext.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while handling xhr send', err); });
325
+ }
326
+ });
327
+ }
311
328
  /* eslint-disable-next-line @typescript-eslint/no-unsafe-argument */
312
329
  return originalXhrSend.apply(xhrSafe, args);
313
330
  };
@@ -320,15 +337,17 @@ var NetworkObserver = /** @class */ (function () {
320
337
  // allow "any" type for args to reflect how it's used in the browser
321
338
  /* eslint-disable-next-line @typescript-eslint/no-unsafe-argument */
322
339
  xhrProto.setRequestHeader = function (headerName, headerValue) {
323
- var _a;
324
340
  var xhrSafe = this;
325
341
  try {
326
- /* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */
327
- xhrSafe.$$AmplitudeAnalyticsEvent.headers[headerName] = headerValue;
342
+ var analyticsEvent = xhrSafe.$$AmplitudeAnalyticsEvent;
343
+ if (analyticsEvent) {
344
+ /* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */
345
+ analyticsEvent.headers[headerName] = headerValue;
346
+ }
328
347
  }
329
348
  catch (err) {
330
349
  /* istanbul ignore next */
331
- (_a = networkObserverContext.logger) === null || _a === void 0 ? void 0 : _a.error('an unexpected error occurred while calling xhr setRequestHeader', err);
350
+ safeInvoke(function () { var _a; return (_a = networkObserverContext.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while calling xhr setRequestHeader', err); });
332
351
  }
333
352
  /* eslint-disable-next-line @typescript-eslint/no-unsafe-argument */
334
353
  originalXhrSetRequestHeader.apply(xhrSafe, [headerName, headerValue]);