@amplitude/analytics-core 2.39.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.
- package/lib/cjs/diagnostics/uncaught-sdk-errors.d.ts.map +1 -1
- package/lib/cjs/diagnostics/uncaught-sdk-errors.js +42 -12
- package/lib/cjs/diagnostics/uncaught-sdk-errors.js.map +1 -1
- package/lib/cjs/index.d.ts +5 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +13 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/messenger/background-capture.d.ts +13 -0
- package/lib/cjs/messenger/background-capture.d.ts.map +1 -0
- package/lib/cjs/messenger/background-capture.js +64 -0
- package/lib/cjs/messenger/background-capture.js.map +1 -0
- package/lib/cjs/messenger/base-window-messenger.d.ts +100 -0
- package/lib/cjs/messenger/base-window-messenger.d.ts.map +1 -0
- package/lib/cjs/messenger/base-window-messenger.js +261 -0
- package/lib/cjs/messenger/base-window-messenger.js.map +1 -0
- package/lib/cjs/messenger/constants.d.ts +6 -0
- package/lib/cjs/messenger/constants.d.ts.map +1 -0
- package/lib/cjs/messenger/constants.js +15 -0
- package/lib/cjs/messenger/constants.js.map +1 -0
- package/lib/cjs/messenger/utils.d.ts +12 -0
- package/lib/cjs/messenger/utils.d.ts.map +1 -0
- package/lib/cjs/messenger/utils.js +48 -0
- package/lib/cjs/messenger/utils.js.map +1 -0
- package/lib/cjs/observers/network.d.ts.map +1 -1
- package/lib/cjs/observers/network.js +58 -39
- package/lib/cjs/observers/network.js.map +1 -1
- package/lib/cjs/types/element-interactions.d.ts +0 -1
- package/lib/cjs/types/element-interactions.d.ts.map +1 -1
- package/lib/cjs/types/element-interactions.js.map +1 -1
- package/lib/cjs/utils/safe-stringify.d.ts +4 -0
- package/lib/cjs/utils/safe-stringify.d.ts.map +1 -0
- package/lib/cjs/utils/safe-stringify.js +9 -0
- package/lib/cjs/utils/safe-stringify.js.map +1 -0
- package/lib/esm/diagnostics/uncaught-sdk-errors.d.ts.map +1 -1
- package/lib/esm/diagnostics/uncaught-sdk-errors.js +43 -13
- package/lib/esm/diagnostics/uncaught-sdk-errors.js.map +1 -1
- package/lib/esm/index.d.ts +5 -0
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +4 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/messenger/background-capture.d.ts +13 -0
- package/lib/esm/messenger/background-capture.d.ts.map +1 -0
- package/lib/esm/messenger/background-capture.js +60 -0
- package/lib/esm/messenger/background-capture.js.map +1 -0
- package/lib/esm/messenger/base-window-messenger.d.ts +100 -0
- package/lib/esm/messenger/base-window-messenger.d.ts.map +1 -0
- package/lib/esm/messenger/base-window-messenger.js +257 -0
- package/lib/esm/messenger/base-window-messenger.js.map +1 -0
- package/lib/esm/messenger/constants.d.ts +6 -0
- package/lib/esm/messenger/constants.d.ts.map +1 -0
- package/lib/esm/messenger/constants.js +12 -0
- package/lib/esm/messenger/constants.js.map +1 -0
- package/lib/esm/messenger/utils.d.ts +12 -0
- package/lib/esm/messenger/utils.d.ts.map +1 -0
- package/lib/esm/messenger/utils.js +43 -0
- package/lib/esm/messenger/utils.js.map +1 -0
- package/lib/esm/observers/network.d.ts.map +1 -1
- package/lib/esm/observers/network.js +58 -39
- package/lib/esm/observers/network.js.map +1 -1
- package/lib/esm/types/element-interactions.d.ts +0 -1
- package/lib/esm/types/element-interactions.d.ts.map +1 -1
- package/lib/esm/types/element-interactions.js.map +1 -1
- package/lib/esm/utils/safe-stringify.d.ts +4 -0
- package/lib/esm/utils/safe-stringify.d.ts.map +1 -0
- package/lib/esm/utils/safe-stringify.js +6 -0
- package/lib/esm/utils/safe-stringify.js.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.getOrCreateWindowMessenger = void 0;
|
|
5
|
+
var tslib_1 = require("tslib");
|
|
6
|
+
var global_scope_1 = require("../global-scope");
|
|
7
|
+
var constants_1 = require("./constants");
|
|
8
|
+
var utils_1 = require("./utils");
|
|
9
|
+
/**
|
|
10
|
+
* Brand key used to identify BaseWindowMessenger instances across bundle boundaries.
|
|
11
|
+
*/
|
|
12
|
+
var MESSENGER_BRAND = '__AMPLITUDE_MESSENGER_INSTANCE__';
|
|
13
|
+
/** Global scope key where the singleton messenger is stored. */
|
|
14
|
+
var MESSENGER_GLOBAL_KEY = '__AMPLITUDE_MESSENGER__';
|
|
15
|
+
/**
|
|
16
|
+
* BaseWindowMessenger provides generic cross-window communication via postMessage.
|
|
17
|
+
* Singleton access via getOrCreateWindowMessenger() to prevent duplicate instances
|
|
18
|
+
*/
|
|
19
|
+
var BaseWindowMessenger = /** @class */ (function () {
|
|
20
|
+
function BaseWindowMessenger(_b) {
|
|
21
|
+
var _c = _b === void 0 ? {} : _b, _d = _c.origin, origin = _d === void 0 ? constants_1.AMPLITUDE_ORIGIN : _d;
|
|
22
|
+
/** Brand property for cross-bundle instanceof checks. */
|
|
23
|
+
this[_a] = true;
|
|
24
|
+
this.isSetup = false;
|
|
25
|
+
this.messageHandler = null;
|
|
26
|
+
this.requestCallbacks = {};
|
|
27
|
+
this.actionHandlers = new Map();
|
|
28
|
+
/**
|
|
29
|
+
* Messages received for actions that had no registered handler yet.
|
|
30
|
+
* Drained automatically when the corresponding handler is registered via
|
|
31
|
+
* registerActionHandler(), solving startup race conditions between
|
|
32
|
+
* independently-initialized plugins.
|
|
33
|
+
*/
|
|
34
|
+
this.pendingMessages = new Map();
|
|
35
|
+
/**
|
|
36
|
+
* Tracks in-flight and completed script loads by URL.
|
|
37
|
+
* Using a map, this prevents duplicate loads before the first resolves.
|
|
38
|
+
*/
|
|
39
|
+
this.scriptLoadPromises = new Map();
|
|
40
|
+
this.endpoint = origin;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Send a message to the parent window (window.opener).
|
|
44
|
+
*/
|
|
45
|
+
BaseWindowMessenger.prototype.notify = function (message) {
|
|
46
|
+
var _b, _c, _d, _e;
|
|
47
|
+
(_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));
|
|
48
|
+
(_e = (_d = window.opener) === null || _d === void 0 ? void 0 : _d.postMessage) === null || _e === void 0 ? void 0 : _e.call(_d, message, this.endpoint);
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Send an async request to the parent window with a unique ID.
|
|
52
|
+
* Returns a Promise that resolves when the parent responds.
|
|
53
|
+
*/
|
|
54
|
+
BaseWindowMessenger.prototype.sendRequest = function (action, args, options) {
|
|
55
|
+
var _this = this;
|
|
56
|
+
if (options === void 0) { options = { timeout: 15000 }; }
|
|
57
|
+
var id = (0, utils_1.generateUniqueId)();
|
|
58
|
+
var request = { id: id, action: action, args: args };
|
|
59
|
+
var promise = new Promise(function (resolve, reject) {
|
|
60
|
+
_this.requestCallbacks[id] = { resolve: resolve, reject: reject };
|
|
61
|
+
_this.notify(request);
|
|
62
|
+
if (options.timeout > 0) {
|
|
63
|
+
setTimeout(function () {
|
|
64
|
+
reject(new Error("".concat(action, " timed out (id: ").concat(id, ")")));
|
|
65
|
+
delete _this.requestCallbacks[id];
|
|
66
|
+
}, options.timeout);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return promise;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Handle a response to a previous request by resolving its Promise.
|
|
73
|
+
*/
|
|
74
|
+
BaseWindowMessenger.prototype.handleResponse = function (response) {
|
|
75
|
+
var _b;
|
|
76
|
+
if (!this.requestCallbacks[response.id]) {
|
|
77
|
+
(_b = this.logger) === null || _b === void 0 ? void 0 : _b.warn("No callback found for request id: ".concat(response.id));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
this.requestCallbacks[response.id].resolve(response.responseData);
|
|
81
|
+
delete this.requestCallbacks[response.id];
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Register a handler for a specific action type.
|
|
85
|
+
* Logs a warning if overwriting an existing handler.
|
|
86
|
+
*/
|
|
87
|
+
BaseWindowMessenger.prototype.registerActionHandler = function (action, handler) {
|
|
88
|
+
var e_1, _b;
|
|
89
|
+
var _c, _d;
|
|
90
|
+
if (this.actionHandlers.has(action)) {
|
|
91
|
+
(_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));
|
|
92
|
+
}
|
|
93
|
+
this.actionHandlers.set(action, handler);
|
|
94
|
+
// Replay any messages that arrived before this handler was registered
|
|
95
|
+
var queued = this.pendingMessages.get(action);
|
|
96
|
+
if (queued) {
|
|
97
|
+
this.pendingMessages.delete(action);
|
|
98
|
+
try {
|
|
99
|
+
for (var queued_1 = tslib_1.__values(queued), queued_1_1 = queued_1.next(); !queued_1_1.done; queued_1_1 = queued_1.next()) {
|
|
100
|
+
var data = queued_1_1.value;
|
|
101
|
+
handler(data);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
105
|
+
finally {
|
|
106
|
+
try {
|
|
107
|
+
if (queued_1_1 && !queued_1_1.done && (_b = queued_1.return)) _b.call(queued_1);
|
|
108
|
+
}
|
|
109
|
+
finally { if (e_1) throw e_1.error; }
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Load a script once, deduplicating by URL.
|
|
115
|
+
* Safe against concurrent calls — the second call awaits the first's in-flight Promise
|
|
116
|
+
* rather than triggering a duplicate load.
|
|
117
|
+
*/
|
|
118
|
+
BaseWindowMessenger.prototype.loadScriptOnce = function (url) {
|
|
119
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
120
|
+
var existing, loadPromise, error_1;
|
|
121
|
+
return tslib_1.__generator(this, function (_b) {
|
|
122
|
+
switch (_b.label) {
|
|
123
|
+
case 0:
|
|
124
|
+
existing = this.scriptLoadPromises.get(url);
|
|
125
|
+
if (existing) {
|
|
126
|
+
return [2 /*return*/, existing];
|
|
127
|
+
}
|
|
128
|
+
loadPromise = (0, utils_1.asyncLoadScript)(url).then(function () {
|
|
129
|
+
// Resolve to void
|
|
130
|
+
});
|
|
131
|
+
this.scriptLoadPromises.set(url, loadPromise);
|
|
132
|
+
_b.label = 1;
|
|
133
|
+
case 1:
|
|
134
|
+
_b.trys.push([1, 3, , 4]);
|
|
135
|
+
return [4 /*yield*/, loadPromise];
|
|
136
|
+
case 2:
|
|
137
|
+
_b.sent();
|
|
138
|
+
return [3 /*break*/, 4];
|
|
139
|
+
case 3:
|
|
140
|
+
error_1 = _b.sent();
|
|
141
|
+
// Remove failed loads so they can be retried
|
|
142
|
+
this.scriptLoadPromises.delete(url);
|
|
143
|
+
throw error_1;
|
|
144
|
+
case 4: return [2 /*return*/];
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Set up the message listener. Idempotent — safe to call multiple times.
|
|
151
|
+
* Subclasses should call super.setup() and then register their own action handlers.
|
|
152
|
+
*/
|
|
153
|
+
BaseWindowMessenger.prototype.setup = function (_b) {
|
|
154
|
+
var _this = this;
|
|
155
|
+
var _c, _d;
|
|
156
|
+
var _e = _b === void 0 ? {} : _b, logger = _e.logger, endpoint = _e.endpoint;
|
|
157
|
+
if (logger) {
|
|
158
|
+
this.logger = logger;
|
|
159
|
+
}
|
|
160
|
+
// If endpoint is customized, don't override a previously customized endpoint.
|
|
161
|
+
if (endpoint && this.endpoint === constants_1.AMPLITUDE_ORIGIN) {
|
|
162
|
+
this.endpoint = endpoint;
|
|
163
|
+
}
|
|
164
|
+
// Only attach the message listener once
|
|
165
|
+
if (this.isSetup) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
this.isSetup = true;
|
|
169
|
+
(_d = (_c = this.logger) === null || _c === void 0 ? void 0 : _c.debug) === null || _d === void 0 ? void 0 : _d.call(_c, 'Setting up messenger');
|
|
170
|
+
// Attach Event Listener to listen for messages from the parent window
|
|
171
|
+
this.messageHandler = function (event) {
|
|
172
|
+
var _b, _c, _d, _e, _f;
|
|
173
|
+
(_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));
|
|
174
|
+
// Only accept messages from the specified origin
|
|
175
|
+
if (_this.endpoint !== event.origin) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
var eventData = event.data;
|
|
179
|
+
var action = eventData === null || eventData === void 0 ? void 0 : eventData.action;
|
|
180
|
+
// Ignore messages without action
|
|
181
|
+
if (!action) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
// If id exists, handle responses to previous requests
|
|
185
|
+
if ('id' in eventData && eventData.id) {
|
|
186
|
+
(_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));
|
|
187
|
+
_this.handleResponse(eventData);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
if (action === 'ping') {
|
|
191
|
+
_this.notify({ action: 'pong' });
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
// Dispatch to registered action handlers, or buffer for late registration
|
|
195
|
+
var handler = _this.actionHandlers.get(action);
|
|
196
|
+
if (handler) {
|
|
197
|
+
handler(eventData.data);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
var queue = (_f = _this.pendingMessages.get(action)) !== null && _f !== void 0 ? _f : [];
|
|
201
|
+
queue.push(eventData.data);
|
|
202
|
+
_this.pendingMessages.set(action, queue);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
window.addEventListener('message', this.messageHandler);
|
|
207
|
+
this.notify({ action: 'page-loaded' });
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Tear down the messenger: remove the message listener, clear all state.
|
|
211
|
+
*/
|
|
212
|
+
BaseWindowMessenger.prototype.destroy = function () {
|
|
213
|
+
if (this.messageHandler) {
|
|
214
|
+
window.removeEventListener('message', this.messageHandler);
|
|
215
|
+
this.messageHandler = null;
|
|
216
|
+
}
|
|
217
|
+
this.isSetup = false;
|
|
218
|
+
this.actionHandlers.clear();
|
|
219
|
+
this.pendingMessages.clear();
|
|
220
|
+
this.requestCallbacks = {};
|
|
221
|
+
this.scriptLoadPromises.clear();
|
|
222
|
+
// Remove from global scope if this is the singleton
|
|
223
|
+
var globalScope = (0, global_scope_1.getGlobalScope)();
|
|
224
|
+
if ((globalScope === null || globalScope === void 0 ? void 0 : globalScope[MESSENGER_GLOBAL_KEY]) === this) {
|
|
225
|
+
delete globalScope[MESSENGER_GLOBAL_KEY];
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
return BaseWindowMessenger;
|
|
229
|
+
}());
|
|
230
|
+
_a = MESSENGER_BRAND;
|
|
231
|
+
/**
|
|
232
|
+
* Type guard: checks whether a value is a BaseWindowMessenger instance.
|
|
233
|
+
*/
|
|
234
|
+
function isWindowMessenger(value) {
|
|
235
|
+
return (typeof value === 'object' &&
|
|
236
|
+
value !== null &&
|
|
237
|
+
MESSENGER_BRAND in value &&
|
|
238
|
+
value[MESSENGER_BRAND] === true);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get or create a singleton BaseWindowMessenger instance.
|
|
242
|
+
* Ensures only one messenger (and one message listener) exists per page,
|
|
243
|
+
* preventing duplicate script loads and double notifications.
|
|
244
|
+
*
|
|
245
|
+
* The singleton is stored on globalScope under the same MESSENGER_KEY.
|
|
246
|
+
* The branded property check verifies the stored value is actually a messenger.
|
|
247
|
+
*/
|
|
248
|
+
function getOrCreateWindowMessenger(options) {
|
|
249
|
+
var globalScope = (0, global_scope_1.getGlobalScope)();
|
|
250
|
+
var existing = globalScope === null || globalScope === void 0 ? void 0 : globalScope[MESSENGER_GLOBAL_KEY];
|
|
251
|
+
if (isWindowMessenger(existing)) {
|
|
252
|
+
return existing;
|
|
253
|
+
}
|
|
254
|
+
var messenger = new BaseWindowMessenger(options);
|
|
255
|
+
if (globalScope) {
|
|
256
|
+
globalScope[MESSENGER_GLOBAL_KEY] = messenger;
|
|
257
|
+
}
|
|
258
|
+
return messenger;
|
|
259
|
+
}
|
|
260
|
+
exports.getOrCreateWindowMessenger = getOrCreateWindowMessenger;
|
|
261
|
+
//# 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,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AMPLITUDE_BACKGROUND_CAPTURE_SCRIPT_URL = exports.AMPLITUDE_ORIGINS_MAP = exports.AMPLITUDE_ORIGIN_STAGING = exports.AMPLITUDE_ORIGIN_EU = exports.AMPLITUDE_ORIGIN = void 0;
|
|
4
|
+
// Shared origin constants for Amplitude cross-window communication
|
|
5
|
+
exports.AMPLITUDE_ORIGIN = 'https://app.amplitude.com';
|
|
6
|
+
exports.AMPLITUDE_ORIGIN_EU = 'https://app.eu.amplitude.com';
|
|
7
|
+
exports.AMPLITUDE_ORIGIN_STAGING = 'https://apps.stag2.amplitude.com';
|
|
8
|
+
exports.AMPLITUDE_ORIGINS_MAP = {
|
|
9
|
+
US: exports.AMPLITUDE_ORIGIN,
|
|
10
|
+
EU: exports.AMPLITUDE_ORIGIN_EU,
|
|
11
|
+
STAGING: exports.AMPLITUDE_ORIGIN_STAGING,
|
|
12
|
+
};
|
|
13
|
+
// Background capture script URL (shared between autocapture and session-replay)
|
|
14
|
+
exports.AMPLITUDE_BACKGROUND_CAPTURE_SCRIPT_URL = 'https://cdn.amplitude.com/libs/background-capture-1.0.0-alpha.1.js.gz';
|
|
15
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/messenger/constants.ts"],"names":[],"mappings":";;;AAAA,mEAAmE;AACtD,QAAA,gBAAgB,GAAG,2BAA2B,CAAC;AAC/C,QAAA,mBAAmB,GAAG,8BAA8B,CAAC;AACrD,QAAA,wBAAwB,GAAG,kCAAkC,CAAC;AAC9D,QAAA,qBAAqB,GAA2B;IAC3D,EAAE,EAAE,wBAAgB;IACpB,EAAE,EAAE,2BAAmB;IACvB,OAAO,EAAE,gCAAwB;CAClC,CAAC;AAEF,gFAAgF;AACnE,QAAA,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,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable no-restricted-globals */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.generateUniqueId = exports.asyncLoadScript = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* Dynamically loads an external script by appending a <script> tag to the document head.
|
|
7
|
+
* Deduplicates by checking if a script with the same src already exists.
|
|
8
|
+
*/
|
|
9
|
+
var asyncLoadScript = function (url) {
|
|
10
|
+
// Dedup: if a script with this src already exists, resolve immediately
|
|
11
|
+
var existing = document.querySelector("script[src=\"".concat(CSS.escape(url), "\"]"));
|
|
12
|
+
if (existing) {
|
|
13
|
+
return Promise.resolve({ status: true });
|
|
14
|
+
}
|
|
15
|
+
return new Promise(function (resolve, reject) {
|
|
16
|
+
var _a;
|
|
17
|
+
try {
|
|
18
|
+
var scriptElement = document.createElement('script');
|
|
19
|
+
scriptElement.type = 'text/javascript';
|
|
20
|
+
scriptElement.async = true;
|
|
21
|
+
scriptElement.src = url;
|
|
22
|
+
scriptElement.addEventListener('load', function () {
|
|
23
|
+
resolve({ status: true });
|
|
24
|
+
}, { once: true });
|
|
25
|
+
scriptElement.addEventListener('error', function () {
|
|
26
|
+
reject({
|
|
27
|
+
status: false,
|
|
28
|
+
message: "Failed to load the script ".concat(url),
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
/* istanbul ignore next */
|
|
32
|
+
(_a = document.head) === null || _a === void 0 ? void 0 : _a.appendChild(scriptElement);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
/* istanbul ignore next */
|
|
36
|
+
reject(error);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
exports.asyncLoadScript = asyncLoadScript;
|
|
41
|
+
/**
|
|
42
|
+
* Generates a simple unique ID for message request/response correlation.
|
|
43
|
+
*/
|
|
44
|
+
function generateUniqueId() {
|
|
45
|
+
return "".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
|
|
46
|
+
}
|
|
47
|
+
exports.generateUniqueId = generateUniqueId;
|
|
48
|
+
//# 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;AACI,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;AAjCW,QAAA,eAAe,mBAiC1B;AAEF;;GAEG;AACH,SAAgB,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;AAFD,4CAEC","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;
|
|
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"}
|
|
@@ -20,6 +20,14 @@ var NetworkEventCallback = /** @class */ (function () {
|
|
|
20
20
|
return NetworkEventCallback;
|
|
21
21
|
}());
|
|
22
22
|
exports.NetworkEventCallback = NetworkEventCallback;
|
|
23
|
+
function safeInvoke(fn) {
|
|
24
|
+
try {
|
|
25
|
+
fn();
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
// swallow the error
|
|
29
|
+
}
|
|
30
|
+
}
|
|
23
31
|
var NetworkObserver = /** @class */ (function () {
|
|
24
32
|
function NetworkObserver(logger) {
|
|
25
33
|
this.eventCallbacks = new Map();
|
|
@@ -71,15 +79,17 @@ var NetworkObserver = /** @class */ (function () {
|
|
|
71
79
|
NetworkObserver.prototype.triggerEventCallbacks = function (event) {
|
|
72
80
|
var _this = this;
|
|
73
81
|
this.eventCallbacks.forEach(function (callback) {
|
|
74
|
-
var _a;
|
|
75
82
|
try {
|
|
76
83
|
callback.callback(event);
|
|
77
84
|
}
|
|
78
85
|
catch (err) {
|
|
79
86
|
// if the callback throws an error, we should catch it
|
|
80
87
|
// to avoid breaking the fetch promise chain
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
safeInvoke(function () {
|
|
89
|
+
var _a;
|
|
90
|
+
/* istanbul ignore next */
|
|
91
|
+
(_a = _this.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while triggering event callbacks', err);
|
|
92
|
+
});
|
|
83
93
|
}
|
|
84
94
|
});
|
|
85
95
|
};
|
|
@@ -151,26 +161,26 @@ var NetworkObserver = /** @class */ (function () {
|
|
|
151
161
|
*/
|
|
152
162
|
this.globalScope.fetch = function (requestInfo, requestInit) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
153
163
|
var timestamps, originalResponse, originalError, err_1;
|
|
154
|
-
var
|
|
155
|
-
return tslib_1.__generator(this, function (
|
|
156
|
-
switch (
|
|
164
|
+
var _this = this;
|
|
165
|
+
return tslib_1.__generator(this, function (_a) {
|
|
166
|
+
switch (_a.label) {
|
|
157
167
|
case 0:
|
|
158
168
|
try {
|
|
159
169
|
timestamps = this.getTimestamps();
|
|
160
170
|
}
|
|
161
171
|
catch (error) {
|
|
162
172
|
/* istanbul ignore next */
|
|
163
|
-
(_a =
|
|
173
|
+
safeInvoke(function () { var _a; return (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while retrieving timestamps', error); });
|
|
164
174
|
}
|
|
165
|
-
|
|
175
|
+
_a.label = 1;
|
|
166
176
|
case 1:
|
|
167
|
-
|
|
177
|
+
_a.trys.push([1, 3, , 4]);
|
|
168
178
|
return [4 /*yield*/, originalFetch(requestInfo, requestInit)];
|
|
169
179
|
case 2:
|
|
170
|
-
originalResponse =
|
|
180
|
+
originalResponse = _a.sent();
|
|
171
181
|
return [3 /*break*/, 4];
|
|
172
182
|
case 3:
|
|
173
|
-
err_1 =
|
|
183
|
+
err_1 = _a.sent();
|
|
174
184
|
// Capture error information
|
|
175
185
|
originalError = err_1;
|
|
176
186
|
return [3 /*break*/, 4];
|
|
@@ -187,7 +197,7 @@ var NetworkObserver = /** @class */ (function () {
|
|
|
187
197
|
// this catch shouldn't be reachable, but keep it here for safety
|
|
188
198
|
// because we're overriding the fetch function and better to be safe than sorry
|
|
189
199
|
/* istanbul ignore next */
|
|
190
|
-
(
|
|
200
|
+
safeInvoke(function () { var _a; return (_a = _this.logger) === null || _a === void 0 ? void 0 : _a.debug('an unexpected error occurred while handling fetch', err); });
|
|
191
201
|
}
|
|
192
202
|
// 4. return the original response or throw the original error
|
|
193
203
|
if (originalResponse) {
|
|
@@ -214,7 +224,7 @@ var NetworkObserver = /** @class */ (function () {
|
|
|
214
224
|
*/
|
|
215
225
|
NetworkObserver.createXhrJsonParser = function (xhrUnsafe, context) {
|
|
216
226
|
return function () {
|
|
217
|
-
var _a
|
|
227
|
+
var _a;
|
|
218
228
|
try {
|
|
219
229
|
if (xhrUnsafe.responseType === 'json') {
|
|
220
230
|
// if response is a JS object, clone it so that subscribers can't mutate it
|
|
@@ -234,7 +244,10 @@ var NetworkObserver = /** @class */ (function () {
|
|
|
234
244
|
if (err instanceof Error && err.name === 'InvalidStateError') {
|
|
235
245
|
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText#exceptions
|
|
236
246
|
// if we reach here, it means we don't handle responseType correctly
|
|
237
|
-
(
|
|
247
|
+
safeInvoke(function () {
|
|
248
|
+
var _a;
|
|
249
|
+
return (_a = context.logger) === null || _a === void 0 ? void 0 : _a.debug("unexpected error when retrieving responseText. responseType='".concat(xhrUnsafe.responseType, "'"));
|
|
250
|
+
});
|
|
238
251
|
}
|
|
239
252
|
// the other possible error is Json Parse error which we fail silently
|
|
240
253
|
return null;
|
|
@@ -256,20 +269,20 @@ var NetworkObserver = /** @class */ (function () {
|
|
|
256
269
|
* and make sure another developer who is an expert reviews this change throughly
|
|
257
270
|
*/
|
|
258
271
|
xhrProto.open = function () {
|
|
259
|
-
var _a
|
|
272
|
+
var _a;
|
|
260
273
|
var args = [];
|
|
261
274
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
262
275
|
args[_i] = arguments[_i];
|
|
263
276
|
}
|
|
264
277
|
var xhrSafe = this;
|
|
265
|
-
var
|
|
278
|
+
var _b = tslib_1.__read(args, 2), method = _b[0], url = _b[1];
|
|
266
279
|
try {
|
|
267
280
|
/* istanbul ignore next */
|
|
268
281
|
xhrSafe.$$AmplitudeAnalyticsEvent = tslib_1.__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());
|
|
269
282
|
}
|
|
270
283
|
catch (err) {
|
|
271
284
|
/* istanbul ignore next */
|
|
272
|
-
(
|
|
285
|
+
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); });
|
|
273
286
|
}
|
|
274
287
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
275
288
|
return originalXhrOpen.apply(xhrSafe, args);
|
|
@@ -293,24 +306,28 @@ var NetworkObserver = /** @class */ (function () {
|
|
|
293
306
|
var getJson = NetworkObserver.createXhrJsonParser(xhrUnsafe, networkObserverContext);
|
|
294
307
|
var body = args[0];
|
|
295
308
|
var requestEvent = xhrSafe.$$AmplitudeAnalyticsEvent;
|
|
296
|
-
xhrSafe
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
309
|
+
// if xhrSafe.$$AmplitudeAnalyticsEvent is not set, it means that
|
|
310
|
+
// the xhr.open method was called before we monkey-patched XHR and
|
|
311
|
+
// the event is missed
|
|
312
|
+
if (xhrSafe.$$AmplitudeAnalyticsEvent) {
|
|
313
|
+
xhrSafe.addEventListener('loadend', function () {
|
|
314
|
+
try {
|
|
315
|
+
var responseHeaders = xhrSafe.getAllResponseHeaders();
|
|
316
|
+
var responseBodySize = xhrSafe.getResponseHeader('content-length');
|
|
317
|
+
var responseWrapper = new network_request_event_1.ResponseWrapperXhr(xhrSafe.status, responseHeaders,
|
|
318
|
+
/* istanbul ignore next */
|
|
319
|
+
responseBodySize ? parseInt(responseBodySize, 10) : undefined, getJson);
|
|
320
|
+
var requestHeaders = xhrSafe.$$AmplitudeAnalyticsEvent.headers;
|
|
321
|
+
var requestWrapper = new network_request_event_1.RequestWrapperXhr(body, requestHeaders);
|
|
322
|
+
requestEvent.status = xhrSafe.status;
|
|
323
|
+
networkObserverContext.handleNetworkRequestEvent('xhr', { url: requestEvent.url, method: requestEvent.method }, requestWrapper, responseWrapper, undefined, requestEvent.startTime, requestEvent.durationStart);
|
|
324
|
+
}
|
|
325
|
+
catch (err) {
|
|
326
|
+
/* istanbul ignore next */
|
|
327
|
+
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); });
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
}
|
|
314
331
|
/* eslint-disable-next-line @typescript-eslint/no-unsafe-argument */
|
|
315
332
|
return originalXhrSend.apply(xhrSafe, args);
|
|
316
333
|
};
|
|
@@ -323,15 +340,17 @@ var NetworkObserver = /** @class */ (function () {
|
|
|
323
340
|
// allow "any" type for args to reflect how it's used in the browser
|
|
324
341
|
/* eslint-disable-next-line @typescript-eslint/no-unsafe-argument */
|
|
325
342
|
xhrProto.setRequestHeader = function (headerName, headerValue) {
|
|
326
|
-
var _a;
|
|
327
343
|
var xhrSafe = this;
|
|
328
344
|
try {
|
|
329
|
-
|
|
330
|
-
|
|
345
|
+
var analyticsEvent = xhrSafe.$$AmplitudeAnalyticsEvent;
|
|
346
|
+
if (analyticsEvent) {
|
|
347
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */
|
|
348
|
+
analyticsEvent.headers[headerName] = headerValue;
|
|
349
|
+
}
|
|
331
350
|
}
|
|
332
351
|
catch (err) {
|
|
333
352
|
/* istanbul ignore next */
|
|
334
|
-
(_a = networkObserverContext.logger) === null || _a === void 0 ? void 0 : _a.
|
|
353
|
+
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); });
|
|
335
354
|
}
|
|
336
355
|
/* eslint-disable-next-line @typescript-eslint/no-unsafe-argument */
|
|
337
356
|
originalXhrSetRequestHeader.apply(xhrSafe, [headerName, headerValue]);
|