@newrelic/browser-agent 1.232.1 → 1.233.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 (233) hide show
  1. package/dist/cjs/cdn/polyfills.js +5 -2
  2. package/dist/cjs/common/config/state/configurable.js +15 -26
  3. package/dist/cjs/common/config/state/info.js +1 -1
  4. package/dist/cjs/common/config/state/init.js +101 -56
  5. package/dist/cjs/common/config/state/loader-config.js +1 -1
  6. package/dist/cjs/common/config/state/runtime.js +1 -5
  7. package/dist/cjs/common/constants/env.cdn.js +1 -1
  8. package/dist/cjs/common/constants/env.npm.js +1 -1
  9. package/dist/cjs/common/drain/drain.js +1 -1
  10. package/dist/cjs/common/harvest/harvest-scheduler.js +30 -10
  11. package/dist/cjs/common/harvest/harvest.js +119 -55
  12. package/dist/cjs/common/session/session-entity.js +35 -22
  13. package/dist/cjs/common/session/session-entity.test.js +73 -49
  14. package/dist/cjs/common/timer/interaction-timer.js +9 -12
  15. package/dist/cjs/common/url/protocol.test.js +0 -1
  16. package/dist/cjs/common/util/feature-flags.js +2 -1
  17. package/dist/cjs/common/util/submit-data.js +57 -18
  18. package/dist/cjs/common/wrap/wrap-fetch.js +1 -1
  19. package/dist/cjs/common/wrap/wrap-function.js +1 -1
  20. package/dist/cjs/common/wrap/wrap-promise.js +1 -1
  21. package/dist/cjs/features/ajax/aggregate/index.js +2 -2
  22. package/dist/cjs/features/jserrors/aggregate/index.js +7 -5
  23. package/dist/cjs/features/metrics/aggregate/framework-detection.js +67 -0
  24. package/dist/cjs/features/metrics/aggregate/framework-detection.test.js +137 -0
  25. package/dist/cjs/features/metrics/aggregate/index.js +7 -3
  26. package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.js +14 -0
  27. package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.test.js +17 -0
  28. package/dist/cjs/features/metrics/aggregate/polyfill-detection.js +53 -0
  29. package/dist/cjs/features/metrics/aggregate/polyfill-detection.test.js +165 -0
  30. package/dist/cjs/features/page_action/aggregate/index.js +2 -2
  31. package/dist/cjs/features/page_view_event/aggregate/index.js +6 -3
  32. package/dist/cjs/features/page_view_timing/aggregate/index.js +2 -2
  33. package/dist/cjs/features/session_replay/aggregate/index.js +333 -0
  34. package/dist/cjs/features/session_replay/constants.js +9 -0
  35. package/dist/cjs/features/session_replay/index.js +12 -0
  36. package/dist/cjs/features/session_replay/instrument/index.js +29 -0
  37. package/dist/cjs/features/session_trace/aggregate/index.js +163 -162
  38. package/dist/cjs/features/session_trace/constants.js +2 -9
  39. package/dist/cjs/features/session_trace/instrument/index.js +24 -66
  40. package/dist/cjs/features/spa/aggregate/index.js +2 -2
  41. package/dist/cjs/features/utils/agent-session.js +1 -2
  42. package/dist/cjs/features/utils/aggregate-base.js +64 -0
  43. package/dist/cjs/features/utils/feature-base.js +0 -31
  44. package/dist/cjs/features/utils/handler-cache.js +3 -4
  45. package/dist/cjs/features/utils/instrument-base.js +42 -10
  46. package/dist/cjs/features/utils/{lazy-loader.js → lazy-feature-loader.js} +4 -2
  47. package/dist/cjs/loaders/agent.js +1 -1
  48. package/dist/cjs/loaders/api/apiAsync.js +3 -1
  49. package/dist/cjs/loaders/configure/configure.js +3 -3
  50. package/dist/cjs/loaders/features/featureDependencies.js +0 -12
  51. package/dist/cjs/loaders/features/features.js +3 -1
  52. package/dist/cjs/loaders/micro-agent.js +6 -6
  53. package/dist/esm/cdn/polyfills.js +5 -2
  54. package/dist/esm/common/config/state/configurable.js +14 -24
  55. package/dist/esm/common/config/state/info.js +2 -2
  56. package/dist/esm/common/config/state/init.js +102 -57
  57. package/dist/esm/common/config/state/loader-config.js +2 -2
  58. package/dist/esm/common/config/state/runtime.js +2 -4
  59. package/dist/esm/common/constants/env.cdn.js +1 -1
  60. package/dist/esm/common/constants/env.npm.js +1 -1
  61. package/dist/esm/common/drain/drain.js +1 -1
  62. package/dist/esm/common/harvest/harvest-scheduler.js +30 -10
  63. package/dist/esm/common/harvest/harvest.js +121 -56
  64. package/dist/esm/common/session/session-entity.js +35 -22
  65. package/dist/esm/common/session/session-entity.test.js +73 -49
  66. package/dist/esm/common/timer/interaction-timer.js +9 -12
  67. package/dist/esm/common/url/protocol.test.js +0 -1
  68. package/dist/esm/common/util/feature-flags.js +2 -1
  69. package/dist/esm/common/util/submit-data.js +57 -18
  70. package/dist/esm/common/wrap/wrap-fetch.js +1 -1
  71. package/dist/esm/common/wrap/wrap-function.js +1 -1
  72. package/dist/esm/common/wrap/wrap-promise.js +1 -1
  73. package/dist/esm/features/ajax/aggregate/index.js +2 -2
  74. package/dist/esm/features/jserrors/aggregate/index.js +7 -5
  75. package/dist/esm/features/metrics/aggregate/framework-detection.js +61 -0
  76. package/dist/esm/features/metrics/aggregate/framework-detection.test.js +133 -0
  77. package/dist/esm/features/metrics/aggregate/index.js +7 -3
  78. package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.js +8 -0
  79. package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.test.js +15 -0
  80. package/dist/esm/features/metrics/aggregate/polyfill-detection.js +47 -0
  81. package/dist/esm/features/metrics/aggregate/polyfill-detection.test.js +163 -0
  82. package/dist/esm/features/page_action/aggregate/index.js +2 -2
  83. package/dist/esm/features/page_view_event/aggregate/index.js +6 -3
  84. package/dist/esm/features/page_view_timing/aggregate/index.js +2 -2
  85. package/dist/esm/features/session_replay/aggregate/index.js +327 -0
  86. package/dist/esm/features/session_replay/constants.js +2 -0
  87. package/dist/esm/features/session_replay/index.js +12 -0
  88. package/dist/esm/features/session_replay/instrument/index.js +21 -0
  89. package/dist/esm/features/session_trace/aggregate/index.js +163 -162
  90. package/dist/esm/features/session_trace/constants.js +1 -5
  91. package/dist/esm/features/session_trace/instrument/index.js +24 -66
  92. package/dist/esm/features/spa/aggregate/index.js +2 -2
  93. package/dist/esm/features/utils/agent-session.js +1 -2
  94. package/dist/esm/features/utils/aggregate-base.js +57 -0
  95. package/dist/esm/features/utils/feature-base.js +1 -32
  96. package/dist/esm/features/utils/handler-cache.js +3 -4
  97. package/dist/esm/features/utils/instrument-base.js +42 -10
  98. package/dist/esm/features/utils/{lazy-loader.js → lazy-feature-loader.js} +3 -1
  99. package/dist/esm/loaders/agent.js +1 -1
  100. package/dist/esm/loaders/api/apiAsync.js +3 -1
  101. package/dist/esm/loaders/configure/configure.js +3 -3
  102. package/dist/esm/loaders/features/featureDependencies.js +0 -11
  103. package/dist/esm/loaders/features/features.js +3 -1
  104. package/dist/esm/loaders/micro-agent.js +6 -6
  105. package/dist/types/common/config/state/configurable.d.ts +1 -3
  106. package/dist/types/common/config/state/configurable.d.ts.map +1 -1
  107. package/dist/types/common/config/state/init.d.ts.map +1 -1
  108. package/dist/types/common/config/state/runtime.d.ts.map +1 -1
  109. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  110. package/dist/types/common/harvest/harvest.d.ts +37 -34
  111. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  112. package/dist/types/common/session/session-entity.d.ts +6 -3
  113. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  114. package/dist/types/common/timer/interaction-timer.d.ts +2 -1
  115. package/dist/types/common/timer/interaction-timer.d.ts.map +1 -1
  116. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  117. package/dist/types/common/util/submit-data.d.ts +40 -14
  118. package/dist/types/common/util/submit-data.d.ts.map +1 -1
  119. package/dist/types/features/ajax/aggregate/index.d.ts +2 -2
  120. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  121. package/dist/types/features/jserrors/aggregate/index.d.ts +2 -2
  122. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  123. package/dist/types/features/metrics/aggregate/framework-detection.d.ts.map +1 -0
  124. package/dist/types/features/metrics/aggregate/index.d.ts +2 -2
  125. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  126. package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts +6 -0
  127. package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts.map +1 -0
  128. package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts +7 -0
  129. package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts.map +1 -0
  130. package/dist/types/features/page_action/aggregate/index.d.ts +2 -2
  131. package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
  132. package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -2
  133. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  134. package/dist/types/features/page_view_timing/aggregate/index.d.ts +2 -2
  135. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  136. package/dist/types/features/session_replay/aggregate/index.d.ts +96 -0
  137. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -0
  138. package/dist/types/features/session_replay/constants.d.ts +2 -0
  139. package/dist/types/features/session_replay/constants.d.ts.map +1 -0
  140. package/dist/types/features/session_replay/index.d.ts +2 -0
  141. package/dist/types/features/session_replay/index.d.ts.map +1 -0
  142. package/dist/types/features/session_replay/instrument/index.d.ts +6 -0
  143. package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -0
  144. package/dist/types/features/session_trace/aggregate/index.d.ts +8 -57
  145. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  146. package/dist/types/features/session_trace/constants.d.ts +0 -3
  147. package/dist/types/features/session_trace/constants.d.ts.map +1 -1
  148. package/dist/types/features/session_trace/instrument/index.d.ts +1 -3
  149. package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
  150. package/dist/types/features/spa/aggregate/index.d.ts +2 -2
  151. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  152. package/dist/types/features/utils/agent-session.d.ts.map +1 -1
  153. package/dist/types/features/utils/aggregate-base.d.ts +11 -0
  154. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -0
  155. package/dist/types/features/utils/feature-base.d.ts +0 -5
  156. package/dist/types/features/utils/feature-base.d.ts.map +1 -1
  157. package/dist/types/features/utils/handler-cache.d.ts.map +1 -1
  158. package/dist/types/features/utils/instrument-base.d.ts +3 -1
  159. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  160. package/dist/types/features/utils/{lazy-loader.d.ts → lazy-feature-loader.d.ts} +2 -2
  161. package/dist/types/features/utils/lazy-feature-loader.d.ts.map +1 -0
  162. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  163. package/dist/types/loaders/features/featureDependencies.d.ts +0 -1
  164. package/dist/types/loaders/features/featureDependencies.d.ts.map +1 -1
  165. package/dist/types/loaders/features/features.d.ts +1 -0
  166. package/dist/types/loaders/features/features.d.ts.map +1 -1
  167. package/package.json +28 -19
  168. package/src/cdn/polyfills.js +4 -1
  169. package/src/common/config/state/configurable.js +18 -24
  170. package/src/common/config/state/info.js +2 -2
  171. package/src/common/config/state/init.js +62 -28
  172. package/src/common/config/state/loader-config.js +2 -2
  173. package/src/common/config/state/runtime.js +2 -4
  174. package/src/common/drain/drain.js +1 -1
  175. package/src/common/harvest/harvest-scheduler.js +35 -10
  176. package/src/common/harvest/harvest.js +73 -50
  177. package/src/common/session/session-entity.js +34 -23
  178. package/src/common/session/session-entity.test.js +57 -51
  179. package/src/common/timer/interaction-timer.js +9 -12
  180. package/src/common/url/protocol.test.js +0 -1
  181. package/src/common/util/feature-flags.js +2 -2
  182. package/src/common/util/submit-data.js +28 -17
  183. package/src/common/wrap/wrap-fetch.js +1 -1
  184. package/src/common/wrap/wrap-function.js +1 -1
  185. package/src/common/wrap/wrap-promise.js +1 -1
  186. package/src/features/ajax/aggregate/index.js +2 -2
  187. package/src/features/jserrors/aggregate/index.js +7 -5
  188. package/src/features/metrics/aggregate/framework-detection.js +73 -0
  189. package/src/features/metrics/aggregate/framework-detection.test.js +201 -0
  190. package/src/features/metrics/aggregate/index.js +8 -3
  191. package/src/features/metrics/aggregate/polyfill-detection.es5.js +9 -0
  192. package/src/features/metrics/aggregate/polyfill-detection.es5.test.js +16 -0
  193. package/src/features/metrics/aggregate/polyfill-detection.js +48 -0
  194. package/src/features/metrics/aggregate/polyfill-detection.test.js +163 -0
  195. package/src/features/page_action/aggregate/index.js +2 -2
  196. package/src/features/page_view_event/aggregate/index.js +5 -5
  197. package/src/features/page_view_timing/aggregate/index.js +2 -2
  198. package/src/features/session_replay/aggregate/index.js +314 -0
  199. package/src/features/session_replay/constants.js +3 -0
  200. package/src/features/session_replay/index.js +12 -0
  201. package/src/features/session_replay/instrument/index.js +22 -0
  202. package/src/features/session_trace/aggregate/index.js +148 -187
  203. package/src/features/session_trace/constants.js +0 -4
  204. package/src/features/session_trace/instrument/index.js +17 -69
  205. package/src/features/spa/aggregate/index.js +2 -2
  206. package/src/features/utils/agent-session.js +1 -2
  207. package/src/features/utils/aggregate-base.js +51 -0
  208. package/src/features/utils/feature-base.js +1 -31
  209. package/src/features/utils/handler-cache.js +3 -4
  210. package/src/features/utils/instrument-base.js +40 -8
  211. package/src/features/utils/{lazy-loader.js → lazy-feature-loader.js} +3 -1
  212. package/src/loaders/agent.js +1 -1
  213. package/src/loaders/api/apiAsync.js +1 -1
  214. package/src/loaders/configure/configure.js +4 -3
  215. package/src/loaders/features/featureDependencies.js +0 -12
  216. package/src/loaders/features/features.js +3 -1
  217. package/src/loaders/micro-agent.js +4 -4
  218. package/dist/cjs/common/metrics/framework-detection.js +0 -72
  219. package/dist/cjs/common/util/user-agent.js +0 -57
  220. package/dist/cjs/common/window/supports-performance-observer.js +0 -15
  221. package/dist/esm/common/metrics/framework-detection.js +0 -66
  222. package/dist/esm/common/util/user-agent.js +0 -48
  223. package/dist/esm/common/window/supports-performance-observer.js +0 -9
  224. package/dist/types/common/metrics/framework-detection.d.ts.map +0 -1
  225. package/dist/types/common/util/user-agent.d.ts +0 -5
  226. package/dist/types/common/util/user-agent.d.ts.map +0 -1
  227. package/dist/types/common/window/supports-performance-observer.d.ts +0 -2
  228. package/dist/types/common/window/supports-performance-observer.d.ts.map +0 -1
  229. package/dist/types/features/utils/lazy-loader.d.ts.map +0 -1
  230. package/src/common/metrics/framework-detection.js +0 -71
  231. package/src/common/util/user-agent.js +0 -56
  232. package/src/common/window/supports-performance-observer.js +0 -10
  233. /package/dist/types/{common/metrics → features/metrics/aggregate}/framework-detection.d.ts +0 -0
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.SessionEntity = void 0;
6
+ exports.SessionEntity = exports.SESSION_EVENTS = void 0;
7
7
  var _uniqueId = require("../ids/unique-id");
8
8
  var _console = require("../util/console");
9
9
  var _stringify = require("../util/stringify");
@@ -18,15 +18,23 @@ var _configurable = require("../config/state/configurable");
18
18
  var _handle = require("../event-emitter/handle");
19
19
  var _constants2 = require("../../features/metrics/constants");
20
20
  var _features = require("../../loaders/features/features");
21
+ // this is what can be stored in local storage (not enforced but probably should be)
22
+ // these values should sync between local storage and the parent class props
21
23
  const model = {
22
24
  value: '',
23
25
  inactiveAt: 0,
24
26
  expiresAt: 0,
25
27
  updatedAt: Date.now(),
26
- sessionReplayActive: false,
28
+ sessionReplay: 0,
27
29
  sessionTraceActive: false,
28
30
  custom: {}
29
31
  };
32
+ const SESSION_EVENTS = {
33
+ PAUSE: 'session-pause',
34
+ RESET: 'session-reset',
35
+ RESUME: 'session-resume'
36
+ };
37
+ exports.SESSION_EVENTS = SESSION_EVENTS;
30
38
  class SessionEntity {
31
39
  /**
32
40
  * Create a self-managing Session Entity. This entity is scoped to the agent identifier which triggered it, allowing for multiple simultaneous session objects to exist.
@@ -48,13 +56,13 @@ class SessionEntity {
48
56
  } = _ref;
49
57
  if (!agentIdentifier || !key) throw new Error('Missing Required Fields');
50
58
  if (!_globalScope.isBrowserScope) this.storage = new _localMemory.LocalMemory();else this.storage = storageAPI;
59
+ this.state = {};
51
60
  this.sync(model);
52
61
  this.agentIdentifier = agentIdentifier;
53
-
54
62
  // key is intended to act as the k=v pair
55
63
  this.key = key;
56
64
  // value is intended to act as the primary value of the k=v pair
57
- this.value = value;
65
+ this.state.value = value;
58
66
  this.expiresMs = expiresMs;
59
67
  this.inactiveMs = inactiveMs;
60
68
  this.ee = _contextualEe.ee.get(agentIdentifier);
@@ -71,7 +79,7 @@ class SessionEntity {
71
79
  // the set-up of the timer used to expire the session "naturally" at a certain time
72
80
  // this gets ignored if the value is falsy, allowing for session entities that do not expire
73
81
  if (expiresMs) {
74
- this.expiresAt = initialRead?.expiresAt || this.getFutureTimestamp(expiresMs);
82
+ this.state.expiresAt = initialRead?.expiresAt || this.getFutureTimestamp(expiresMs);
75
83
  this.expiresTimer = new _timer.Timer({
76
84
  // When the inactive timer ends, collect a SM and reset the session
77
85
  onEnd: () => {
@@ -79,16 +87,16 @@ class SessionEntity {
79
87
  this.collectSM('duration', this);
80
88
  this.reset();
81
89
  }
82
- }, this.expiresAt - Date.now());
90
+ }, this.state.expiresAt - Date.now());
83
91
  } else {
84
- this.expiresAt = Infinity;
92
+ this.state.expiresAt = Infinity;
85
93
  }
86
94
 
87
95
  // the set-up of the timer used to expire the session due to "inactivity" at a certain time
88
96
  // this gets ignored if the value is falsy, allowing for session entities that do not expire
89
97
  // this gets "refreshed" when "activity" is observed
90
98
  if (inactiveMs) {
91
- this.inactiveAt = initialRead?.inactiveAt || this.getFutureTimestamp(inactiveMs);
99
+ this.state.inactiveAt = initialRead?.inactiveAt || this.getFutureTimestamp(inactiveMs);
92
100
  this.inactiveTimer = new _interactionTimer.InteractionTimer({
93
101
  // When the inactive timer ends, collect a SM and reset the session
94
102
  onEnd: () => {
@@ -98,21 +106,27 @@ class SessionEntity {
98
106
  },
99
107
  // When the inactive timer refreshes, it will update the storage values with an update timestamp
100
108
  onRefresh: this.refresh.bind(this),
109
+ onResume: () => {
110
+ this.ee.emit(SESSION_EVENTS.RESUME);
111
+ },
101
112
  // When the inactive timer pauses, update the storage values with an update timestamp
102
- onPause: () => this.write(new _configurable.Configurable(this.read(), model)),
113
+ onPause: () => {
114
+ if (this.initialized) this.ee.emit(SESSION_EVENTS.PAUSE);
115
+ this.write((0, _configurable.getModeledObject)(this.state, model));
116
+ },
103
117
  ee: this.ee,
104
118
  refreshEvents: ['click', 'keydown', 'scroll']
105
- }, this.inactiveAt - Date.now());
119
+ }, this.state.inactiveAt - Date.now());
106
120
  } else {
107
- this.inactiveAt = Infinity;
121
+ this.state.inactiveAt = Infinity;
108
122
  }
109
123
 
110
124
  // The fact that the session is "new" or pre-existing is used in some places in the agent. Session Replay and Trace
111
125
  // can use this info to inform whether to trust a new sampling decision vs continue a previous tracking effort.
112
- this.isNew = !Object.keys(initialRead).length;
126
+ if (this.isNew === undefined) this.isNew = !Object.keys(initialRead).length;
113
127
  // if its a "new" session, we write to storage API with the default values. These values may change over the lifespan of the agent run.
114
- // we can use configurable here to help us know and manage what values are being used. -- see "model" above
115
- if (this.isNew) this.write(new _configurable.Configurable(this, model), true);else this.sync(initialRead);
128
+ // we can use a modeled object here to help us know and manage what values are being used. -- see "model" above
129
+ if (this.isNew) this.write((0, _configurable.getModeledObject)(this.state, model), true);else this.sync(initialRead);
116
130
  this.initialized = true;
117
131
  }
118
132
 
@@ -121,7 +135,7 @@ class SessionEntity {
121
135
  return "".concat(_constants.PREFIX, "_").concat(this.key);
122
136
  }
123
137
  sync(data) {
124
- Object.assign(this, data);
138
+ Object.assign(this.state, data);
125
139
  }
126
140
 
127
141
  /**
@@ -168,7 +182,8 @@ class SessionEntity {
168
182
  if (!data || typeof data !== 'object') return;
169
183
  // everytime we update, we can update a timestamp for sanity
170
184
  data.updatedAt = Date.now();
171
- this.sync(data);
185
+ this.sync(data); // update the parent class "state" properties with the local storage values
186
+ //
172
187
  // TODO - compression would need happen here if we decide to do it
173
188
  this.storage.set(this.lookupKey, (0, _stringify.stringify)(data));
174
189
  return data;
@@ -184,12 +199,11 @@ class SessionEntity {
184
199
  // * stop recording (stn and sr)...
185
200
  // * delete the session and start over
186
201
  try {
187
- if (this.initialized) this.ee.emit('session-reset');
202
+ if (this.initialized) this.ee.emit(SESSION_EVENTS.RESET);
188
203
  this.storage.remove(this.lookupKey);
189
204
  this.inactiveTimer?.abort?.();
190
205
  this.expiresTimer?.clear?.();
191
- delete this.custom;
192
- delete this.value;
206
+ delete this.isNew;
193
207
  this.setup({
194
208
  agentIdentifier: this.agentIdentifier,
195
209
  key: this.key,
@@ -209,10 +223,9 @@ class SessionEntity {
209
223
  refresh() {
210
224
  // read here & invalidate
211
225
  const existingData = this.read();
212
- this.inactiveAt = this.getFutureTimestamp(this.inactiveMs);
213
226
  this.write({
214
227
  ...existingData,
215
- inactiveAt: this.inactiveAt
228
+ inactiveAt: this.getFutureTimestamp(this.inactiveMs)
216
229
  });
217
230
  }
218
231
 
@@ -229,7 +242,7 @@ class SessionEntity {
229
242
  * @returns {boolean}
230
243
  */
231
244
  isInvalid(data) {
232
- const requiredKeys = ['value', 'expiresAt', 'inactiveAt'];
245
+ const requiredKeys = Object.keys(model);
233
246
  return !requiredKeys.every(x => Object.keys(data).includes(x));
234
247
  }
235
248
  collectSM(type, data, useUpdatedAt) {
@@ -38,17 +38,19 @@ describe('constructor', () => {
38
38
  expect(session).toMatchObject({
39
39
  agentIdentifier: expect.any(String),
40
40
  key: expect.any(String),
41
- value: expect.any(String),
42
41
  expiresMs: expect.any(Number),
43
- expiresAt: expect.any(Number),
44
42
  expiresTimer: expect.any(Object),
45
43
  inactiveMs: expect.any(Number),
46
- inactiveAt: expect.any(Number),
47
44
  inactiveTimer: expect.any(Object),
48
45
  isNew: expect.any(Boolean),
49
- sessionReplayActive: expect.any(Boolean),
50
- sessionTraceActive: expect.any(Boolean),
51
- storage: expect.any(Object)
46
+ storage: expect.any(Object),
47
+ state: expect.objectContaining({
48
+ value: expect.any(String),
49
+ expiresAt: expect.any(Number),
50
+ inactiveAt: expect.any(Number),
51
+ sessionReplay: expect.any(Number),
52
+ sessionTraceActive: expect.any(Boolean)
53
+ })
52
54
  });
53
55
  });
54
56
  test('can use sane defaults', () => {
@@ -56,11 +58,12 @@ describe('constructor', () => {
56
58
  agentIdentifier,
57
59
  key
58
60
  });
59
- expect(session).toEqual(expect.objectContaining({
61
+ expect(session.state).toEqual(expect.objectContaining({
60
62
  value: expect.any(String),
61
63
  expiresAt: expect.any(Number),
62
64
  inactiveAt: expect.any(Number),
63
- sessionReplayActive: expect.any(Boolean),
65
+ updatedAt: expect.any(Number),
66
+ sessionReplay: expect.any(Number),
64
67
  sessionTraceActive: expect.any(Boolean)
65
68
  }));
66
69
  });
@@ -81,7 +84,7 @@ describe('constructor', () => {
81
84
  key,
82
85
  expiresMs: 100
83
86
  });
84
- expect(session.expiresAt).toEqual(now + 100);
87
+ expect(session.state.expiresAt).toEqual(now + 100);
85
88
  });
86
89
  test('expiresAt is the correct future timestamp - existing session', () => {
87
90
  const now = Date.now();
@@ -90,7 +93,11 @@ describe('constructor', () => {
90
93
  ["".concat(_constants.PREFIX, "_").concat(key)]: {
91
94
  value,
92
95
  expiresAt: now + 5000,
93
- inactiveAt: Infinity
96
+ inactiveAt: Infinity,
97
+ updatedAt: now,
98
+ sessionReplay: 0,
99
+ sessionTraceActive: false,
100
+ custom: {}
94
101
  }
95
102
  });
96
103
  const session = new _sessionEntity.SessionEntity({
@@ -99,7 +106,7 @@ describe('constructor', () => {
99
106
  expiresMs: 100,
100
107
  storageAPI: existingData
101
108
  });
102
- expect(session.expiresAt).toEqual(now + 5000);
109
+ expect(session.state.expiresAt).toEqual(now + 5000);
103
110
  });
104
111
  test('expiresAt never expires if 0', () => {
105
112
  const session = new _sessionEntity.SessionEntity({
@@ -107,7 +114,7 @@ describe('constructor', () => {
107
114
  key,
108
115
  expiresMs: 0
109
116
  });
110
- expect(session.expiresAt).toEqual(Infinity);
117
+ expect(session.state.expiresAt).toEqual(Infinity);
111
118
  });
112
119
  test('inactiveAt is the correct future timestamp - new session', () => {
113
120
  const now = Date.now();
@@ -117,7 +124,7 @@ describe('constructor', () => {
117
124
  key,
118
125
  inactiveMs: 100
119
126
  });
120
- expect(session.inactiveAt).toEqual(now + 100);
127
+ expect(session.state.inactiveAt).toEqual(now + 100);
121
128
  });
122
129
  test('inactiveAt is the correct future timestamp - existing session', () => {
123
130
  const now = Date.now();
@@ -126,7 +133,11 @@ describe('constructor', () => {
126
133
  ["".concat(_constants.PREFIX, "_").concat(key)]: {
127
134
  value,
128
135
  inactiveAt: now + 5000,
129
- expiresAt: Infinity
136
+ expiresAt: Infinity,
137
+ updatedAt: now,
138
+ sessionReplay: 0,
139
+ sessionTraceActive: false,
140
+ custom: {}
130
141
  }
131
142
  });
132
143
  const session = new _sessionEntity.SessionEntity({
@@ -135,7 +146,7 @@ describe('constructor', () => {
135
146
  inactiveMs: 100,
136
147
  storageAPI: existingData
137
148
  });
138
- expect(session.inactiveAt).toEqual(now + 5000);
149
+ expect(session.state.inactiveAt).toEqual(now + 5000);
139
150
  });
140
151
  test('inactiveAt never expires if 0', () => {
141
152
  const session = new _sessionEntity.SessionEntity({
@@ -143,7 +154,7 @@ describe('constructor', () => {
143
154
  key,
144
155
  inactiveMs: 0
145
156
  });
146
- expect(session.inactiveAt).toEqual(Infinity);
157
+ expect(session.state.inactiveAt).toEqual(Infinity);
147
158
  });
148
159
  test('should handle isNew', () => {
149
160
  const newSession = new _sessionEntity.SessionEntity({
@@ -156,7 +167,11 @@ describe('constructor', () => {
156
167
  ["".concat(_constants.PREFIX, "_").concat(key)]: {
157
168
  value,
158
169
  expiresAt: Infinity,
159
- inactiveAt: Infinity
170
+ inactiveAt: Infinity,
171
+ updatedAt: Date.now(),
172
+ sessionReplay: 0,
173
+ sessionTraceActive: false,
174
+ custom: {}
160
175
  }
161
176
  });
162
177
  const existingSession = new _sessionEntity.SessionEntity({
@@ -179,11 +194,12 @@ describe('constructor', () => {
179
194
  key,
180
195
  storageAPI
181
196
  });
182
- expect(session).toEqual(expect.objectContaining({
197
+ expect(session.state).toEqual(expect.objectContaining({
183
198
  value: expect.any(String),
184
199
  expiresAt: expect.any(Number),
185
200
  inactiveAt: expect.any(Number),
186
- sessionReplayActive: expect.any(Boolean),
201
+ updatedAt: expect.any(Number),
202
+ sessionReplay: expect.any(Number),
187
203
  sessionTraceActive: expect.any(Boolean)
188
204
  }));
189
205
  });
@@ -202,11 +218,12 @@ describe('constructor', () => {
202
218
  key,
203
219
  storageAPI
204
220
  });
205
- expect(session).toEqual(expect.objectContaining({
221
+ expect(session.state).toEqual(expect.objectContaining({
206
222
  value: expect.any(String),
207
223
  expiresAt: expect.any(Number),
208
224
  inactiveAt: expect.any(Number),
209
- sessionReplayActive: expect.any(Boolean),
225
+ updatedAt: expect.any(Number),
226
+ sessionReplay: expect.any(Number),
210
227
  sessionTraceActive: expect.any(Boolean)
211
228
  }));
212
229
  });
@@ -225,11 +242,12 @@ describe('constructor', () => {
225
242
  key,
226
243
  storageAPI
227
244
  });
228
- expect(session).toEqual(expect.objectContaining({
245
+ expect(session.state).toEqual(expect.objectContaining({
229
246
  value: expect.any(String),
230
247
  expiresAt: expect.any(Number),
231
248
  inactiveAt: expect.any(Number),
232
- sessionReplayActive: expect.any(Boolean),
249
+ updatedAt: expect.any(Number),
250
+ sessionReplay: expect.any(Number),
233
251
  sessionTraceActive: expect.any(Boolean)
234
252
  }));
235
253
  });
@@ -244,10 +262,10 @@ describe('reset()', () => {
244
262
  expiresMs: 10
245
263
  });
246
264
  const sessionVal = session.value;
247
- expect(session.value).toBeTruthy();
265
+ expect(session.state.value).toBeTruthy();
248
266
  session.reset();
249
- expect(session.value).toBeTruthy();
250
- expect(session.value).not.toEqual(sessionVal);
267
+ expect(session.state.value).toBeTruthy();
268
+ expect(session.state.value).not.toEqual(sessionVal);
251
269
  });
252
270
  test('custom data should be wiped on reset', () => {
253
271
  const now = Date.now();
@@ -258,12 +276,12 @@ describe('reset()', () => {
258
276
  expiresMs: 10
259
277
  });
260
278
  session.syncCustomAttribute('test', 123);
261
- expect(session.custom.test).toEqual(123);
279
+ expect(session.state.custom.test).toEqual(123);
262
280
  expect(session.read().custom.test).toEqual(123);
263
281
 
264
282
  // simulate a timer expiring
265
283
  session.reset();
266
- expect(session.custom?.test).toEqual(undefined);
284
+ expect(session.state.custom?.test).toEqual(undefined);
267
285
  expect(session.read()?.custom?.test).toEqual(undefined);
268
286
  });
269
287
  });
@@ -279,7 +297,7 @@ describe('read()', () => {
279
297
  value: expect.any(String),
280
298
  expiresAt: expect.any(Number),
281
299
  inactiveAt: expect.any(Number),
282
- sessionReplayActive: expect.any(Boolean),
300
+ sessionReplay: expect.any(Number),
283
301
  sessionTraceActive: expect.any(Boolean)
284
302
  }));
285
303
  });
@@ -288,7 +306,11 @@ describe('read()', () => {
288
306
  ["".concat(_constants.PREFIX, "_").concat(key)]: {
289
307
  value,
290
308
  expiresAt: Infinity,
291
- inactiveAt: Infinity
309
+ inactiveAt: Infinity,
310
+ updatedAt: Date.now(),
311
+ sessionReplay: 0,
312
+ sessionTraceActive: false,
313
+ custom: {}
292
314
  }
293
315
  });
294
316
  const session = new _sessionEntity.SessionEntity({
@@ -310,17 +332,18 @@ describe('write()', () => {
310
332
  agentIdentifier,
311
333
  key
312
334
  });
313
- expect(session.value).not.toEqual(value);
314
- expect(session.expiresAt).not.toEqual(Infinity);
315
- expect(session.inactiveAt).not.toEqual(Infinity);
335
+ expect(session.state.value).not.toEqual(value);
336
+ expect(session.state.expiresAt).not.toEqual(Infinity);
337
+ expect(session.state.inactiveAt).not.toEqual(Infinity);
316
338
  session.write({
339
+ ...session.state,
317
340
  value,
318
341
  expiresAt: Infinity,
319
342
  inactiveAt: Infinity
320
343
  });
321
- expect(session.value).toEqual(value);
322
- expect(session.expiresAt).toEqual(Infinity);
323
- expect(session.inactiveAt).toEqual(Infinity);
344
+ expect(session.state.value).toEqual(value);
345
+ expect(session.state.expiresAt).toEqual(Infinity);
346
+ expect(session.state.inactiveAt).toEqual(Infinity);
324
347
  });
325
348
  test('write() sets data that read() can access', () => {
326
349
  const now = Date.now();
@@ -330,6 +353,7 @@ describe('write()', () => {
330
353
  key
331
354
  });
332
355
  session.write({
356
+ ...session.state,
333
357
  value,
334
358
  expiresAt: now + 100,
335
359
  inactiveAt: now + 100
@@ -365,10 +389,10 @@ describe('refresh()', () => {
365
389
  key,
366
390
  inactiveMs: 100
367
391
  });
368
- expect(session.inactiveAt).toEqual(now + 100);
392
+ expect(session.state.inactiveAt).toEqual(now + 100);
369
393
  jest.setSystemTime(now + 1000);
370
394
  session.refresh();
371
- expect(session.inactiveAt).toEqual(now + 100 + 1000);
395
+ expect(session.state.inactiveAt).toEqual(now + 100 + 1000);
372
396
  });
373
397
  test('refresh resets the entity if expiresTimer is invalid', () => {
374
398
  const now = Date.now();
@@ -378,13 +402,13 @@ describe('refresh()', () => {
378
402
  key,
379
403
  value
380
404
  });
381
- expect(session.value).toEqual(value);
405
+ expect(session.state.value).toEqual(value);
382
406
  session.write({
383
- ...session.read(),
407
+ ...session.state,
384
408
  expiresAt: now - 1
385
409
  });
386
410
  session.refresh();
387
- expect(session.value).not.toEqual(value);
411
+ expect(session.state.value).not.toEqual(value);
388
412
  });
389
413
  test('refresh resets the entity if inactiveTimer is invalid', () => {
390
414
  const now = Date.now();
@@ -394,13 +418,13 @@ describe('refresh()', () => {
394
418
  key,
395
419
  value
396
420
  });
397
- expect(session.value).toEqual(value);
421
+ expect(session.state.value).toEqual(value);
398
422
  session.write({
399
- ...session.read(),
423
+ ...session.state,
400
424
  inactiveAt: now - 1
401
425
  });
402
426
  session.refresh();
403
- expect(session.value).not.toEqual(value);
427
+ expect(session.state.value).not.toEqual(value);
404
428
  });
405
429
  });
406
430
  describe('syncCustomAttribute()', () => {
@@ -412,17 +436,17 @@ describe('syncCustomAttribute()', () => {
412
436
 
413
437
  // if custom has never been set, and a "delete" action is triggered, do nothing
414
438
  session.syncCustomAttribute('test', null);
415
- expect(session?.custom?.test).toEqual(undefined);
439
+ expect(session?.state?.custom?.test).toEqual(undefined);
416
440
  session.syncCustomAttribute('test', 1);
417
- expect(session?.custom?.test).toEqual(1);
441
+ expect(session?.state?.custom?.test).toEqual(1);
418
442
  session.syncCustomAttribute('test', 'string');
419
- expect(session?.custom?.test).toEqual('string');
443
+ expect(session?.state?.custom?.test).toEqual('string');
420
444
  session.syncCustomAttribute('test', false);
421
- expect(session?.custom?.test).toEqual(false);
445
+ expect(session?.state?.custom?.test).toEqual(false);
422
446
 
423
447
  // null specifically deletes the object completely
424
448
  session.syncCustomAttribute('test', null);
425
- expect(session?.custom?.test).toEqual(undefined);
449
+ expect(session?.state?.custom?.test).toEqual(undefined);
426
450
  });
427
451
  test('Only runs in browser scope', () => {
428
452
  mockBrowserScope.mockReturnValue(false);
@@ -11,8 +11,9 @@ var _globalScope = require("../util/global-scope");
11
11
  class InteractionTimer extends _timer.Timer {
12
12
  constructor(opts, ms) {
13
13
  super(opts, ms);
14
- this.onRefresh = opts.onRefresh;
15
- this.onPause = opts.onPause;
14
+ this.onPause = typeof opts.onPause === 'function' ? opts.onPause : () => {/* noop */};
15
+ this.onRefresh = typeof opts.onRefresh === 'function' ? opts.onRefresh : () => {/* noop */};
16
+ this.onResume = typeof opts.onResume === 'function' ? opts.onResume : () => {/* noop */};
16
17
 
17
18
  // used by pause/resume
18
19
  this.remainingMs = undefined;
@@ -47,7 +48,10 @@ class InteractionTimer extends _timer.Timer {
47
48
  (0, _pageVisibility.subscribeToVisibilityChange)(state => {
48
49
  if (state === 'hidden') this.pause();
49
50
  // vis change --> visible is treated like a new interaction with the page
50
- else this.refresh();
51
+ else {
52
+ this.onResume();
53
+ this.refresh();
54
+ }
51
55
  }, false, false, this.abortController?.signal);
52
56
  }
53
57
  }
@@ -56,7 +60,7 @@ class InteractionTimer extends _timer.Timer {
56
60
  this.abortController?.abort();
57
61
  }
58
62
  pause() {
59
- this.onPause?.();
63
+ this.onPause();
60
64
  clearTimeout(this.timer);
61
65
  this.remainingMs = this.initialMs - (Date.now() - this.startTimestamp);
62
66
  }
@@ -65,14 +69,7 @@ class InteractionTimer extends _timer.Timer {
65
69
  this.timer = this.create(cb, ms);
66
70
  this.startTimestamp = Date.now();
67
71
  this.remainingMs = undefined;
68
- this.onRefresh?.();
72
+ this.onRefresh();
69
73
  }
70
-
71
- // NOT CURRENTLY UTILIZED BY ANYTHING
72
- // resume () {
73
- // if (!this.remainingMs || !this.isValid()) return
74
- // this.timer = this.create(this.cb, this.remainingMs)
75
- // this.remainingMs = undefined
76
- // }
77
74
  }
78
75
  exports.InteractionTimer = InteractionTimer;
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
 
3
- var _faker = require("@faker-js/faker");
4
3
  var _protocol = require("./protocol");
5
4
  test('should return true when location url contains file protocol', () => {
6
5
  jest.spyOn(window, 'location', 'get').mockReturnValue({
@@ -19,7 +19,8 @@ const bucketMap = {
19
19
  stn: [_features.FEATURE_NAMES.sessionTrace],
20
20
  err: [_features.FEATURE_NAMES.jserrors, _features.FEATURE_NAMES.metrics],
21
21
  ins: [_features.FEATURE_NAMES.pageAction],
22
- spa: [_features.FEATURE_NAMES.spa]
22
+ spa: [_features.FEATURE_NAMES.spa],
23
+ sr: [_features.FEATURE_NAMES.sessionReplay]
23
24
  };
24
25
  function activateFeatures(flags, agentIdentifier) {
25
26
  var sharedEE = _contextualEe.ee.get(agentIdentifier);
@@ -14,12 +14,18 @@ const submitData = {};
14
14
 
15
15
  /**
16
16
  * Send via JSONP. Do NOT call this function outside of a guaranteed web window environment.
17
- * @param {string} url
18
- * @param {string} jsonp
17
+ * @param {Object} args - The args
18
+ * @param {string} args.url - The URL to send to
19
+ * @param {string} args.jsonp - The string name of the jsonp cb method
20
+ * @returns {XMLHttpRequest}
19
21
  * @returns {Element}
20
22
  */
21
23
  exports.submitData = submitData;
22
- submitData.jsonp = function jsonp(url, jsonp) {
24
+ submitData.jsonp = function jsonp(_ref) {
25
+ let {
26
+ url,
27
+ jsonp
28
+ } = _ref;
23
29
  try {
24
30
  if (_globalScope.isWorkerScope) {
25
31
  try {
@@ -27,7 +33,9 @@ submitData.jsonp = function jsonp(url, jsonp) {
27
33
  } catch (e) {
28
34
  // for now theres no other way to execute the callback from ingest without jsonp, or unsafe eval / new Function calls
29
35
  // future work needs to be conducted to allow ingest to return a more traditional JSON API-like experience for the entitlement flags
30
- submitData.xhrGet(url + '&jsonp=' + jsonp);
36
+ submitData.xhrGet({
37
+ url: url + '&jsonp=' + jsonp
38
+ });
31
39
  return false;
32
40
  }
33
41
  } else {
@@ -42,19 +50,38 @@ submitData.jsonp = function jsonp(url, jsonp) {
42
50
  // do nothing
43
51
  }
44
52
  };
45
- submitData.xhrGet = function xhrGet(url) {
46
- return submitData.xhr(url, undefined, false, 'GET');
53
+ submitData.xhrGet = function xhrGet(_ref2) {
54
+ let {
55
+ url
56
+ } = _ref2;
57
+ return submitData.xhr({
58
+ url,
59
+ sync: false,
60
+ method: 'GET'
61
+ });
47
62
  };
48
63
 
49
64
  /**
50
65
  * Send via XHR
51
- * @param {string} url
52
- * @param {string} body
53
- * @param {boolean} sync
66
+ * @param {Object} args - The args
67
+ * @param {string} args.url - The URL to send to
68
+ * @param {string=} args.body - The Stringified body
69
+ * @param {boolean=} args.sync - Run XHR as Synchronous
70
+ * @param {string=} [args.method=POST] - The XHR method to use
71
+ * @param {{key: string, value: string}[]} [args.headers] - The headers to attach
54
72
  * @returns {XMLHttpRequest}
55
73
  */
56
- submitData.xhr = function xhr(url, body, sync) {
57
- let method = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'POST';
74
+ submitData.xhr = function xhr(_ref3) {
75
+ let {
76
+ url,
77
+ body,
78
+ sync,
79
+ method = 'POST',
80
+ headers = [{
81
+ key: 'content-type',
82
+ value: 'text/plain'
83
+ }]
84
+ } = _ref3;
58
85
  var request = new XMLHttpRequest();
59
86
  request.open(method, url, !sync);
60
87
  try {
@@ -63,7 +90,9 @@ submitData.xhr = function xhr(url, body, sync) {
63
90
  } catch (e) {
64
91
  // do nothing
65
92
  }
66
- request.setRequestHeader('content-type', 'text/plain');
93
+ headers.forEach(header => {
94
+ request.setRequestHeader(header.key, header.value);
95
+ });
67
96
  request.send(body);
68
97
  return request;
69
98
  };
@@ -77,10 +106,15 @@ submitData.xhr = function xhr(url, body, sync) {
77
106
 
78
107
  /**
79
108
  * Send by appending an <img> element to the page. Do NOT call this function outside of a guaranteed web window environment.
80
- * @param {string} url
81
- * @returns {Element}
109
+ * @param {Object} args - The args
110
+ * @param {string} args.url - The URL to send to
111
+ * @returns {HTMLImageElement}
82
112
  */
83
- submitData.img = function img(url) {
113
+ submitData.img = function img(_ref4) {
114
+ let {
115
+ url
116
+ } = _ref4;
117
+ console.log('img url', url);
84
118
  var element = new Image();
85
119
  element.src = url;
86
120
  return element;
@@ -88,11 +122,16 @@ submitData.img = function img(url) {
88
122
 
89
123
  /**
90
124
  * Send via sendBeacon. Do NOT call this function outside of a guaranteed web window environment.
91
- * @param {string} url
92
- * @param {string} body
125
+ * @param {Object} args - The args
126
+ * @param {string} args.url - The URL to send to
127
+ * @param {string=} args.body - The Stringified body
93
128
  * @returns {boolean}
94
129
  */
95
- submitData.beacon = function (url, body) {
130
+ submitData.beacon = function (_ref5) {
131
+ let {
132
+ url,
133
+ body
134
+ } = _ref5;
96
135
  // Navigator has to be bound to ensure it does not error in some browsers
97
136
  // https://xgwang.me/posts/you-may-not-know-beacon/#it-may-throw-error%2C-be-sure-to-catch
98
137
  const send = window.navigator.sendBeacon.bind(window.navigator);