@openreplay/tracker 5.0.5-beta.3 → 5.0.5-beta.6

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/cjs/app/index.js CHANGED
@@ -33,7 +33,7 @@ class App {
33
33
  this.stopCallbacks = [];
34
34
  this.commitCallbacks = [];
35
35
  this.activityState = ActivityState.NotActive;
36
- this.version = '5.0.5-beta.3'; // TODO: version compatability check inside each plugin.
36
+ this.version = '5.0.5-beta.6'; // TODO: version compatability check inside each plugin.
37
37
  this._usingOldFetchPlugin = false;
38
38
  this.delay = 0;
39
39
  this.projectKey = projectKey;
package/cjs/index.js CHANGED
@@ -140,7 +140,7 @@ class API {
140
140
  // no-cors issue only with text/plain or not-set Content-Type
141
141
  // req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
142
142
  req.send(JSON.stringify({
143
- trackerVersion: '5.0.5-beta.3',
143
+ trackerVersion: '5.0.5-beta.6',
144
144
  projectKey: options.projectKey,
145
145
  doNotTrack,
146
146
  // TODO: add precise reason (an exact API missing)
@@ -33,6 +33,7 @@ interface AxiosResponse<T = any> {
33
33
  response?: AxiosRequestConfig;
34
34
  }
35
35
  export interface AxiosInstance extends Record<string, any> {
36
+ getUri: (config?: AxiosRequestConfig) => string;
36
37
  interceptors: {
37
38
  request: AxiosInterceptorManager<InternalAxiosRequestConfig>;
38
39
  response: AxiosInterceptorManager<AxiosResponse>;
@@ -1,71 +1,85 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  const messages_gen_js_1 = require("../app/messages.gen.js");
4
13
  const utils_js_1 = require("../utils.js");
14
+ const exception_js_1 = require("./exception.js");
5
15
  function default_1(app, instance, opts, sanitize, stringify) {
6
16
  app.debug.log('Openreplay: attaching axios spy to instance', instance);
17
+ // eslint-disable-next-line @typescript-eslint/require-await
7
18
  function captureResponseData(axiosResponseObj) {
8
- app.debug.log('Openreplay: capturing axios response data', axiosResponseObj);
9
- const { headers: reqHs, data: reqData, method, url } = axiosResponseObj.config;
10
- const { data: rData, headers: rHs, status: globStatus, response } = axiosResponseObj;
11
- const { data: resData, headers: resHs, status: resStatus } = response || {};
12
- const ihOpt = opts.ignoreHeaders;
13
- const isHIgnoring = Array.isArray(ihOpt) ? (name) => ihOpt.includes(name) : () => ihOpt;
14
- function writeHeader(hsObj, header) {
15
- if (!isHIgnoring(header[0])) {
16
- hsObj[header[0]] = header[1];
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ app.debug.log('Openreplay: capturing axios response data', axiosResponseObj);
21
+ const { headers: reqHs, data: reqData, method, url } = axiosResponseObj.config;
22
+ const { data: rData, headers: rHs, status: globStatus, response } = axiosResponseObj;
23
+ const { data: resData, headers: resHs, status: resStatus } = response || {};
24
+ const ihOpt = opts.ignoreHeaders;
25
+ const isHIgnoring = Array.isArray(ihOpt) ? (name) => ihOpt.includes(name) : () => ihOpt;
26
+ function writeHeader(hsObj, header) {
27
+ if (!isHIgnoring(header[0])) {
28
+ hsObj[header[0]] = header[1];
29
+ }
17
30
  }
18
- }
19
- let requestHs = {};
20
- let responseHs = {};
21
- if (reqHs.toJSON) {
22
- requestHs = reqHs.toJSON();
23
- }
24
- else if (reqHs instanceof Headers) {
25
- reqHs.forEach((v, n) => writeHeader(requestHs, [n, v]));
26
- }
27
- else if (Array.isArray(reqHs)) {
28
- reqHs.forEach((h) => writeHeader(requestHs, h));
29
- }
30
- else if (typeof reqHs === 'object') {
31
- Object.entries(reqHs).forEach((h) => writeHeader(requestHs, h));
32
- }
33
- const usedResHeader = resHs ? resHs : rHs;
34
- if (usedResHeader.toJSON) {
35
- responseHs = usedResHeader.toJSON();
36
- }
37
- else if (usedResHeader instanceof Headers) {
38
- usedResHeader.forEach((v, n) => writeHeader(responseHs, [n, v]));
39
- }
40
- else if (Array.isArray(usedResHeader)) {
41
- usedResHeader.forEach((h) => writeHeader(responseHs, h));
42
- }
43
- else if (typeof usedResHeader === 'object') {
44
- Object.entries(usedResHeader).forEach(([n, v]) => {
45
- if (!isHIgnoring(n))
46
- responseHs[n] = v;
31
+ let requestHs = {};
32
+ let responseHs = {};
33
+ if (reqHs.toJSON) {
34
+ requestHs = reqHs.toJSON();
35
+ }
36
+ else if (reqHs instanceof Headers) {
37
+ reqHs.forEach((v, n) => writeHeader(requestHs, [n, v]));
38
+ }
39
+ else if (Array.isArray(reqHs)) {
40
+ reqHs.forEach((h) => writeHeader(requestHs, h));
41
+ }
42
+ else if (typeof reqHs === 'object') {
43
+ Object.entries(reqHs).forEach((h) => writeHeader(requestHs, h));
44
+ }
45
+ const usedResHeader = resHs ? resHs : rHs;
46
+ if (usedResHeader.toJSON) {
47
+ responseHs = usedResHeader.toJSON();
48
+ }
49
+ else if (usedResHeader instanceof Headers) {
50
+ usedResHeader.forEach((v, n) => writeHeader(responseHs, [n, v]));
51
+ }
52
+ else if (Array.isArray(usedResHeader)) {
53
+ usedResHeader.forEach((h) => writeHeader(responseHs, h));
54
+ }
55
+ else if (typeof usedResHeader === 'object') {
56
+ Object.entries(usedResHeader).forEach(([n, v]) => {
57
+ if (!isHIgnoring(n))
58
+ responseHs[n] = v;
59
+ });
60
+ }
61
+ const reqResInfo = sanitize({
62
+ url,
63
+ method: method || '',
64
+ status: globStatus || resStatus || 0,
65
+ request: {
66
+ headers: requestHs,
67
+ body: reqData,
68
+ },
69
+ response: {
70
+ headers: responseHs,
71
+ body: resData || rData,
72
+ },
47
73
  });
48
- }
49
- const reqResInfo = sanitize({
50
- url,
51
- method: method || '',
52
- status: globStatus || resStatus || 0,
53
- request: {
54
- headers: requestHs,
55
- body: reqData,
56
- },
57
- response: {
58
- headers: responseHs,
59
- body: resData || rData,
60
- },
74
+ if (!reqResInfo) {
75
+ app.debug.log('Openreplay: empty request/response info, skipping');
76
+ return;
77
+ }
78
+ const requestStart = axiosResponseObj.config.__openreplay_timing;
79
+ const duration = performance.now() - requestStart;
80
+ console.log(reqResInfo, 'finally');
81
+ app.send((0, messages_gen_js_1.NetworkRequest)('xhr', String(method), String(reqResInfo.url), stringify(reqResInfo.request), stringify(reqResInfo.response), reqResInfo.status, requestStart + (0, utils_js_1.getTimeOrigin)(), duration));
61
82
  });
62
- if (!reqResInfo) {
63
- app.debug.log('Openreplay: empty request/response info, skipping');
64
- return;
65
- }
66
- const requestStart = axiosResponseObj.config.__openreplay_timing;
67
- const duration = performance.now() - requestStart;
68
- app.send((0, messages_gen_js_1.NetworkRequest)('xhr', String(method), String(reqResInfo.url), stringify(reqResInfo.request), stringify(reqResInfo.response), reqResInfo.status, requestStart + (0, utils_js_1.getTimeOrigin)(), duration));
69
83
  }
70
84
  function getStartTime(config) {
71
85
  app.debug.log('Openreplay: capturing API request', config);
@@ -84,26 +98,29 @@ function default_1(app, instance, opts, sanitize, stringify) {
84
98
  function captureNetworkRequest(response) {
85
99
  if (opts.failuresOnly)
86
100
  return response;
87
- captureResponseData(response);
101
+ void captureResponseData(response);
88
102
  return response;
89
103
  }
90
104
  function captureNetworkError(error) {
91
- captureResponseData(error);
105
+ app.debug.log('Openreplay: capturing API request error', error);
106
+ if (isAxiosError(error)) {
107
+ void captureResponseData(error.response);
108
+ }
109
+ else if (error instanceof Error) {
110
+ app.send((0, exception_js_1.getExceptionMessage)(error, []));
111
+ }
92
112
  return Promise.reject(error);
93
113
  }
94
114
  function logRequestError(ev) {
95
115
  app.debug.log('Openreplay: failed API request, skipping', ev);
96
116
  }
97
- const reqInt = instance.interceptors.request.use(getStartTime, logRequestError, {
98
- synchronous: true,
99
- });
100
- const resInt = instance.interceptors.response.use(captureNetworkRequest, captureNetworkError, {
101
- synchronous: true,
102
- });
103
- app.attachStopCallback(() => {
104
- var _a, _b, _c, _d;
105
- (_b = (_a = instance.interceptors.request).eject) === null || _b === void 0 ? void 0 : _b.call(_a, reqInt);
106
- (_d = (_c = instance.interceptors.response).eject) === null || _d === void 0 ? void 0 : _d.call(_c, resInt);
107
- });
117
+ instance.interceptors.request.use(getStartTime, logRequestError);
118
+ instance.interceptors.response.use(captureNetworkRequest, captureNetworkError);
108
119
  }
109
120
  exports.default = default_1;
121
+ function isAxiosError(payload) {
122
+ return isObject(payload) && payload.isAxiosError === true;
123
+ }
124
+ function isObject(thing) {
125
+ return thing !== null && typeof thing === 'object';
126
+ }
@@ -165,6 +165,7 @@ function default_1(app, opts = {}) {
165
165
  });
166
166
  xhr.addEventListener('load', app.safe((e) => {
167
167
  const { headers: reqHs, body: reqBody } = getXHRRequestDataObject(xhr);
168
+ app.debug.log('Openreplay: XHR load ', reqHs, reqBody, xhr, xhr.getAllResponseHeaders());
168
169
  const duration = startTime > 0 ? e.timeStamp - startTime : 0;
169
170
  const hString = ignoreHeaders ? '' : xhr.getAllResponseHeaders(); // might be null (though only if no response received though)
170
171
  const resHs = hString
@@ -201,10 +202,12 @@ function default_1(app, opts = {}) {
201
202
  XMLHttpRequest.prototype.send = function (body) {
202
203
  const rdo = getXHRRequestDataObject(this);
203
204
  rdo.body = body;
205
+ app.debug.log('Openreplay: ', 'XHR send', rdo, 'XHR Object', this);
204
206
  return nativeSend.apply(this, arguments);
205
207
  };
206
208
  const nativeSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
207
209
  XMLHttpRequest.prototype.setRequestHeader = function (name, value) {
210
+ app.debug.log('Openreplay: ', name, value, isHIgnored(name), getXHRRequestDataObject(this));
208
211
  if (!isHIgnored(name)) {
209
212
  const rdo = getXHRRequestDataObject(this);
210
213
  rdo.headers[name] = value;
package/cjs/utils.d.ts CHANGED
@@ -11,3 +11,4 @@ export declare const DOCS_HOST = "https://docs.openreplay.com";
11
11
  export declare function deprecationWarn(nameOfFeature: string, useInstead: string, docsPath?: string): void;
12
12
  export declare function getLabelAttribute(e: Element): string | null;
13
13
  export declare function hasOpenreplayAttribute(e: Element, attr: string): boolean;
14
+ export declare function buildFullUrl(baseURL: string | undefined, requestedURL: string): string;
package/cjs/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hasOpenreplayAttribute = exports.getLabelAttribute = exports.deprecationWarn = exports.DOCS_HOST = exports.isURL = exports.normSpaces = exports.stars = exports.now = exports.getTimeOrigin = exports.adjustTimeOrigin = exports.MAX_STR_LEN = exports.IS_FIREFOX = exports.IN_BROWSER = void 0;
3
+ exports.buildFullUrl = exports.hasOpenreplayAttribute = exports.getLabelAttribute = exports.deprecationWarn = exports.DOCS_HOST = exports.isURL = exports.normSpaces = exports.stars = exports.now = exports.getTimeOrigin = exports.adjustTimeOrigin = exports.MAX_STR_LEN = exports.IS_FIREFOX = exports.IN_BROWSER = void 0;
4
4
  const DEPRECATED_ATTRS = { htmlmasked: 'hidden', masked: 'obscured' };
5
5
  exports.IN_BROWSER = !(typeof window === 'undefined');
6
6
  exports.IS_FIREFOX = exports.IN_BROWSER && navigator.userAgent.match(/firefox|fxios/i);
@@ -69,3 +69,23 @@ function hasOpenreplayAttribute(e, attr) {
69
69
  return false;
70
70
  }
71
71
  exports.hasOpenreplayAttribute = hasOpenreplayAttribute;
72
+ // Copied from axios library because these functions haven't been exported.
73
+ // Why can't axios put constructed fullURL into the config object or in an additional meta information?
74
+ // TODO: axios feature request
75
+ function isAbsoluteURL(url) {
76
+ // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
77
+ // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
78
+ // by any combination of letters, digits, plus, period, or hyphen.
79
+ // eslint-disable-next-line no-useless-escape
80
+ return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
81
+ }
82
+ function combineURLs(baseURL, relativeURL) {
83
+ return relativeURL ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL;
84
+ }
85
+ function buildFullUrl(baseURL, requestedURL) {
86
+ if (baseURL && !isAbsoluteURL(requestedURL)) {
87
+ return combineURLs(baseURL, requestedURL);
88
+ }
89
+ return requestedURL;
90
+ }
91
+ exports.buildFullUrl = buildFullUrl;
package/lib/app/index.js CHANGED
@@ -30,7 +30,7 @@ export default class App {
30
30
  this.stopCallbacks = [];
31
31
  this.commitCallbacks = [];
32
32
  this.activityState = ActivityState.NotActive;
33
- this.version = '5.0.5-beta.3'; // TODO: version compatability check inside each plugin.
33
+ this.version = '5.0.5-beta.6'; // TODO: version compatability check inside each plugin.
34
34
  this._usingOldFetchPlugin = false;
35
35
  this.delay = 0;
36
36
  this.projectKey = projectKey;
package/lib/index.js CHANGED
@@ -135,7 +135,7 @@ export default class API {
135
135
  // no-cors issue only with text/plain or not-set Content-Type
136
136
  // req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
137
137
  req.send(JSON.stringify({
138
- trackerVersion: '5.0.5-beta.3',
138
+ trackerVersion: '5.0.5-beta.6',
139
139
  projectKey: options.projectKey,
140
140
  doNotTrack,
141
141
  // TODO: add precise reason (an exact API missing)
@@ -33,6 +33,7 @@ interface AxiosResponse<T = any> {
33
33
  response?: AxiosRequestConfig;
34
34
  }
35
35
  export interface AxiosInstance extends Record<string, any> {
36
+ getUri: (config?: AxiosRequestConfig) => string;
36
37
  interceptors: {
37
38
  request: AxiosInterceptorManager<InternalAxiosRequestConfig>;
38
39
  response: AxiosInterceptorManager<AxiosResponse>;
@@ -1,69 +1,83 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import { NetworkRequest } from '../app/messages.gen.js';
2
11
  import { getTimeOrigin } from '../utils.js';
12
+ import { getExceptionMessage } from './exception.js';
3
13
  export default function (app, instance, opts, sanitize, stringify) {
4
14
  app.debug.log('Openreplay: attaching axios spy to instance', instance);
15
+ // eslint-disable-next-line @typescript-eslint/require-await
5
16
  function captureResponseData(axiosResponseObj) {
6
- app.debug.log('Openreplay: capturing axios response data', axiosResponseObj);
7
- const { headers: reqHs, data: reqData, method, url } = axiosResponseObj.config;
8
- const { data: rData, headers: rHs, status: globStatus, response } = axiosResponseObj;
9
- const { data: resData, headers: resHs, status: resStatus } = response || {};
10
- const ihOpt = opts.ignoreHeaders;
11
- const isHIgnoring = Array.isArray(ihOpt) ? (name) => ihOpt.includes(name) : () => ihOpt;
12
- function writeHeader(hsObj, header) {
13
- if (!isHIgnoring(header[0])) {
14
- hsObj[header[0]] = header[1];
17
+ return __awaiter(this, void 0, void 0, function* () {
18
+ app.debug.log('Openreplay: capturing axios response data', axiosResponseObj);
19
+ const { headers: reqHs, data: reqData, method, url } = axiosResponseObj.config;
20
+ const { data: rData, headers: rHs, status: globStatus, response } = axiosResponseObj;
21
+ const { data: resData, headers: resHs, status: resStatus } = response || {};
22
+ const ihOpt = opts.ignoreHeaders;
23
+ const isHIgnoring = Array.isArray(ihOpt) ? (name) => ihOpt.includes(name) : () => ihOpt;
24
+ function writeHeader(hsObj, header) {
25
+ if (!isHIgnoring(header[0])) {
26
+ hsObj[header[0]] = header[1];
27
+ }
15
28
  }
16
- }
17
- let requestHs = {};
18
- let responseHs = {};
19
- if (reqHs.toJSON) {
20
- requestHs = reqHs.toJSON();
21
- }
22
- else if (reqHs instanceof Headers) {
23
- reqHs.forEach((v, n) => writeHeader(requestHs, [n, v]));
24
- }
25
- else if (Array.isArray(reqHs)) {
26
- reqHs.forEach((h) => writeHeader(requestHs, h));
27
- }
28
- else if (typeof reqHs === 'object') {
29
- Object.entries(reqHs).forEach((h) => writeHeader(requestHs, h));
30
- }
31
- const usedResHeader = resHs ? resHs : rHs;
32
- if (usedResHeader.toJSON) {
33
- responseHs = usedResHeader.toJSON();
34
- }
35
- else if (usedResHeader instanceof Headers) {
36
- usedResHeader.forEach((v, n) => writeHeader(responseHs, [n, v]));
37
- }
38
- else if (Array.isArray(usedResHeader)) {
39
- usedResHeader.forEach((h) => writeHeader(responseHs, h));
40
- }
41
- else if (typeof usedResHeader === 'object') {
42
- Object.entries(usedResHeader).forEach(([n, v]) => {
43
- if (!isHIgnoring(n))
44
- responseHs[n] = v;
29
+ let requestHs = {};
30
+ let responseHs = {};
31
+ if (reqHs.toJSON) {
32
+ requestHs = reqHs.toJSON();
33
+ }
34
+ else if (reqHs instanceof Headers) {
35
+ reqHs.forEach((v, n) => writeHeader(requestHs, [n, v]));
36
+ }
37
+ else if (Array.isArray(reqHs)) {
38
+ reqHs.forEach((h) => writeHeader(requestHs, h));
39
+ }
40
+ else if (typeof reqHs === 'object') {
41
+ Object.entries(reqHs).forEach((h) => writeHeader(requestHs, h));
42
+ }
43
+ const usedResHeader = resHs ? resHs : rHs;
44
+ if (usedResHeader.toJSON) {
45
+ responseHs = usedResHeader.toJSON();
46
+ }
47
+ else if (usedResHeader instanceof Headers) {
48
+ usedResHeader.forEach((v, n) => writeHeader(responseHs, [n, v]));
49
+ }
50
+ else if (Array.isArray(usedResHeader)) {
51
+ usedResHeader.forEach((h) => writeHeader(responseHs, h));
52
+ }
53
+ else if (typeof usedResHeader === 'object') {
54
+ Object.entries(usedResHeader).forEach(([n, v]) => {
55
+ if (!isHIgnoring(n))
56
+ responseHs[n] = v;
57
+ });
58
+ }
59
+ const reqResInfo = sanitize({
60
+ url,
61
+ method: method || '',
62
+ status: globStatus || resStatus || 0,
63
+ request: {
64
+ headers: requestHs,
65
+ body: reqData,
66
+ },
67
+ response: {
68
+ headers: responseHs,
69
+ body: resData || rData,
70
+ },
45
71
  });
46
- }
47
- const reqResInfo = sanitize({
48
- url,
49
- method: method || '',
50
- status: globStatus || resStatus || 0,
51
- request: {
52
- headers: requestHs,
53
- body: reqData,
54
- },
55
- response: {
56
- headers: responseHs,
57
- body: resData || rData,
58
- },
72
+ if (!reqResInfo) {
73
+ app.debug.log('Openreplay: empty request/response info, skipping');
74
+ return;
75
+ }
76
+ const requestStart = axiosResponseObj.config.__openreplay_timing;
77
+ const duration = performance.now() - requestStart;
78
+ console.log(reqResInfo, 'finally');
79
+ app.send(NetworkRequest('xhr', String(method), String(reqResInfo.url), stringify(reqResInfo.request), stringify(reqResInfo.response), reqResInfo.status, requestStart + getTimeOrigin(), duration));
59
80
  });
60
- if (!reqResInfo) {
61
- app.debug.log('Openreplay: empty request/response info, skipping');
62
- return;
63
- }
64
- const requestStart = axiosResponseObj.config.__openreplay_timing;
65
- const duration = performance.now() - requestStart;
66
- app.send(NetworkRequest('xhr', String(method), String(reqResInfo.url), stringify(reqResInfo.request), stringify(reqResInfo.response), reqResInfo.status, requestStart + getTimeOrigin(), duration));
67
81
  }
68
82
  function getStartTime(config) {
69
83
  app.debug.log('Openreplay: capturing API request', config);
@@ -82,25 +96,28 @@ export default function (app, instance, opts, sanitize, stringify) {
82
96
  function captureNetworkRequest(response) {
83
97
  if (opts.failuresOnly)
84
98
  return response;
85
- captureResponseData(response);
99
+ void captureResponseData(response);
86
100
  return response;
87
101
  }
88
102
  function captureNetworkError(error) {
89
- captureResponseData(error);
103
+ app.debug.log('Openreplay: capturing API request error', error);
104
+ if (isAxiosError(error)) {
105
+ void captureResponseData(error.response);
106
+ }
107
+ else if (error instanceof Error) {
108
+ app.send(getExceptionMessage(error, []));
109
+ }
90
110
  return Promise.reject(error);
91
111
  }
92
112
  function logRequestError(ev) {
93
113
  app.debug.log('Openreplay: failed API request, skipping', ev);
94
114
  }
95
- const reqInt = instance.interceptors.request.use(getStartTime, logRequestError, {
96
- synchronous: true,
97
- });
98
- const resInt = instance.interceptors.response.use(captureNetworkRequest, captureNetworkError, {
99
- synchronous: true,
100
- });
101
- app.attachStopCallback(() => {
102
- var _a, _b, _c, _d;
103
- (_b = (_a = instance.interceptors.request).eject) === null || _b === void 0 ? void 0 : _b.call(_a, reqInt);
104
- (_d = (_c = instance.interceptors.response).eject) === null || _d === void 0 ? void 0 : _d.call(_c, resInt);
105
- });
115
+ instance.interceptors.request.use(getStartTime, logRequestError);
116
+ instance.interceptors.response.use(captureNetworkRequest, captureNetworkError);
117
+ }
118
+ function isAxiosError(payload) {
119
+ return isObject(payload) && payload.isAxiosError === true;
120
+ }
121
+ function isObject(thing) {
122
+ return thing !== null && typeof thing === 'object';
106
123
  }
@@ -163,6 +163,7 @@ export default function (app, opts = {}) {
163
163
  });
164
164
  xhr.addEventListener('load', app.safe((e) => {
165
165
  const { headers: reqHs, body: reqBody } = getXHRRequestDataObject(xhr);
166
+ app.debug.log('Openreplay: XHR load ', reqHs, reqBody, xhr, xhr.getAllResponseHeaders());
166
167
  const duration = startTime > 0 ? e.timeStamp - startTime : 0;
167
168
  const hString = ignoreHeaders ? '' : xhr.getAllResponseHeaders(); // might be null (though only if no response received though)
168
169
  const resHs = hString
@@ -199,10 +200,12 @@ export default function (app, opts = {}) {
199
200
  XMLHttpRequest.prototype.send = function (body) {
200
201
  const rdo = getXHRRequestDataObject(this);
201
202
  rdo.body = body;
203
+ app.debug.log('Openreplay: ', 'XHR send', rdo, 'XHR Object', this);
202
204
  return nativeSend.apply(this, arguments);
203
205
  };
204
206
  const nativeSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
205
207
  XMLHttpRequest.prototype.setRequestHeader = function (name, value) {
208
+ app.debug.log('Openreplay: ', name, value, isHIgnored(name), getXHRRequestDataObject(this));
206
209
  if (!isHIgnored(name)) {
207
210
  const rdo = getXHRRequestDataObject(this);
208
211
  rdo.headers[name] = value;
package/lib/utils.d.ts CHANGED
@@ -11,3 +11,4 @@ export declare const DOCS_HOST = "https://docs.openreplay.com";
11
11
  export declare function deprecationWarn(nameOfFeature: string, useInstead: string, docsPath?: string): void;
12
12
  export declare function getLabelAttribute(e: Element): string | null;
13
13
  export declare function hasOpenreplayAttribute(e: Element, attr: string): boolean;
14
+ export declare function buildFullUrl(baseURL: string | undefined, requestedURL: string): string;
package/lib/utils.js CHANGED
@@ -59,3 +59,22 @@ export function hasOpenreplayAttribute(e, attr) {
59
59
  }
60
60
  return false;
61
61
  }
62
+ // Copied from axios library because these functions haven't been exported.
63
+ // Why can't axios put constructed fullURL into the config object or in an additional meta information?
64
+ // TODO: axios feature request
65
+ function isAbsoluteURL(url) {
66
+ // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
67
+ // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
68
+ // by any combination of letters, digits, plus, period, or hyphen.
69
+ // eslint-disable-next-line no-useless-escape
70
+ return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
71
+ }
72
+ function combineURLs(baseURL, relativeURL) {
73
+ return relativeURL ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL;
74
+ }
75
+ export function buildFullUrl(baseURL, requestedURL) {
76
+ if (baseURL && !isAbsoluteURL(requestedURL)) {
77
+ return combineURLs(baseURL, requestedURL);
78
+ }
79
+ return requestedURL;
80
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openreplay/tracker",
3
3
  "description": "The OpenReplay tracker main package",
4
- "version": "5.0.5-beta.3",
4
+ "version": "5.0.5-beta.6",
5
5
  "keywords": [
6
6
  "logging",
7
7
  "replay"