@newrelic/browser-agent 1.252.0 → 1.253.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 (217) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +6 -6
  3. package/dist/cjs/cdn/experimental.js +6 -2
  4. package/dist/cjs/cdn/spa.js +5 -3
  5. package/dist/cjs/common/aggregate/aggregator.js +1 -8
  6. package/dist/cjs/common/config/state/init.js +7 -0
  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/context/observation-context-manager.js +56 -0
  10. package/dist/cjs/common/event-emitter/contextual-ee.js +12 -9
  11. package/dist/cjs/common/session/constants.js +2 -1
  12. package/dist/cjs/common/session/session-entity.js +3 -1
  13. package/dist/cjs/common/timing/nav-timing.js +8 -3
  14. package/dist/cjs/common/timing/now.js +1 -1
  15. package/dist/cjs/common/util/feature-flags.js +1 -1
  16. package/dist/cjs/common/wrap/index.js +0 -7
  17. package/dist/cjs/common/wrap/wrap-events.js +2 -2
  18. package/dist/cjs/common/wrap/wrap-fetch.js +2 -1
  19. package/dist/cjs/common/wrap/wrap-function.js +5 -7
  20. package/dist/cjs/common/wrap/wrap-promise.js +2 -1
  21. package/dist/cjs/features/ajax/aggregate/index.js +34 -16
  22. package/dist/cjs/features/jserrors/aggregate/index.js +77 -66
  23. package/dist/cjs/features/page_view_event/aggregate/index.js +1 -1
  24. package/dist/cjs/features/page_view_event/aggregate/initialized-features.js +1 -0
  25. package/dist/cjs/features/session_replay/aggregate/index.js +96 -94
  26. package/dist/cjs/features/session_replay/constants.js +5 -1
  27. package/dist/cjs/features/session_replay/instrument/index.js +24 -8
  28. package/dist/cjs/features/session_replay/shared/recorder.js +5 -4
  29. package/dist/cjs/features/session_replay/shared/stylesheet-evaluator.js +8 -7
  30. package/dist/cjs/features/session_replay/shared/utils.js +26 -0
  31. package/dist/cjs/features/soft_navigations/aggregate/ajax-node.js +50 -0
  32. package/dist/cjs/features/soft_navigations/aggregate/bel-node.js +29 -0
  33. package/dist/cjs/features/soft_navigations/aggregate/index.js +263 -0
  34. package/dist/cjs/features/soft_navigations/aggregate/initial-page-load-interaction.js +62 -0
  35. package/dist/cjs/features/soft_navigations/aggregate/interaction.js +146 -0
  36. package/dist/cjs/features/soft_navigations/constants.js +31 -0
  37. package/dist/cjs/features/soft_navigations/index.js +12 -0
  38. package/dist/cjs/features/soft_navigations/instrument/index.js +79 -0
  39. package/dist/cjs/features/spa/aggregate/index.js +4 -4
  40. package/dist/cjs/features/utils/agent-session.js +2 -1
  41. package/dist/cjs/features/utils/instrument-base.js +6 -9
  42. package/dist/cjs/features/utils/lazy-feature-loader.js +2 -0
  43. package/dist/cjs/loaders/agent-base.js +18 -3
  44. package/dist/cjs/loaders/agent.js +15 -18
  45. package/dist/cjs/loaders/api/api-methods.js +9 -0
  46. package/dist/cjs/loaders/api/api.js +17 -18
  47. package/dist/cjs/loaders/configure/configure.js +5 -2
  48. package/dist/cjs/loaders/features/enabled-features.js +1 -1
  49. package/dist/cjs/loaders/features/features.js +3 -1
  50. package/dist/esm/cdn/experimental.js +5 -2
  51. package/dist/esm/cdn/spa.js +3 -1
  52. package/dist/esm/common/aggregate/aggregator.js +1 -8
  53. package/dist/esm/common/config/state/init.js +7 -0
  54. package/dist/esm/common/constants/env.cdn.js +1 -1
  55. package/dist/esm/common/constants/env.npm.js +1 -1
  56. package/dist/esm/common/context/observation-context-manager.js +49 -0
  57. package/dist/esm/common/event-emitter/contextual-ee.js +12 -9
  58. package/dist/esm/common/session/constants.js +1 -0
  59. package/dist/esm/common/session/session-entity.js +3 -1
  60. package/dist/esm/common/timing/nav-timing.js +8 -3
  61. package/dist/esm/common/timing/now.js +1 -1
  62. package/dist/esm/common/util/feature-flags.js +1 -1
  63. package/dist/esm/common/wrap/index.js +1 -2
  64. package/dist/esm/common/wrap/wrap-events.js +3 -3
  65. package/dist/esm/common/wrap/wrap-fetch.js +3 -2
  66. package/dist/esm/common/wrap/wrap-function.js +4 -5
  67. package/dist/esm/common/wrap/wrap-promise.js +3 -2
  68. package/dist/esm/features/ajax/aggregate/index.js +36 -18
  69. package/dist/esm/features/jserrors/aggregate/index.js +77 -66
  70. package/dist/esm/features/page_view_event/aggregate/index.js +1 -1
  71. package/dist/esm/features/page_view_event/aggregate/initialized-features.js +1 -0
  72. package/dist/esm/features/session_replay/aggregate/index.js +97 -95
  73. package/dist/esm/features/session_replay/constants.js +4 -0
  74. package/dist/esm/features/session_replay/instrument/index.js +25 -9
  75. package/dist/esm/features/session_replay/shared/recorder.js +5 -4
  76. package/dist/esm/features/session_replay/shared/stylesheet-evaluator.js +8 -7
  77. package/dist/esm/features/session_replay/shared/utils.js +17 -0
  78. package/dist/esm/features/soft_navigations/aggregate/ajax-node.js +43 -0
  79. package/dist/esm/features/soft_navigations/aggregate/bel-node.js +22 -0
  80. package/dist/esm/features/soft_navigations/aggregate/index.js +256 -0
  81. package/dist/esm/features/soft_navigations/aggregate/initial-page-load-interaction.js +55 -0
  82. package/dist/esm/features/soft_navigations/aggregate/interaction.js +140 -0
  83. package/dist/esm/features/soft_navigations/constants.js +25 -0
  84. package/dist/esm/features/soft_navigations/index.js +1 -0
  85. package/dist/esm/features/soft_navigations/instrument/index.js +73 -0
  86. package/dist/esm/features/spa/aggregate/index.js +4 -4
  87. package/dist/esm/features/utils/agent-session.js +2 -1
  88. package/dist/esm/features/utils/instrument-base.js +7 -10
  89. package/dist/esm/features/utils/lazy-feature-loader.js +2 -0
  90. package/dist/esm/loaders/agent-base.js +18 -3
  91. package/dist/esm/loaders/agent.js +15 -18
  92. package/dist/esm/loaders/api/api-methods.js +3 -0
  93. package/dist/esm/loaders/api/api.js +17 -17
  94. package/dist/esm/loaders/configure/configure.js +5 -2
  95. package/dist/esm/loaders/features/enabled-features.js +1 -1
  96. package/dist/esm/loaders/features/features.js +3 -1
  97. package/dist/types/common/aggregate/aggregator.d.ts.map +1 -1
  98. package/dist/types/common/config/state/init.d.ts.map +1 -1
  99. package/dist/types/common/context/event-context.d.ts.map +1 -0
  100. package/dist/types/common/context/observation-context-manager.d.ts +28 -0
  101. package/dist/types/common/context/observation-context-manager.d.ts.map +1 -0
  102. package/dist/types/common/event-emitter/contextual-ee.d.ts +2 -2
  103. package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
  104. package/dist/types/common/session/constants.d.ts +1 -0
  105. package/dist/types/common/session/constants.d.ts.map +1 -1
  106. package/dist/types/common/session/session-entity.d.ts +0 -1
  107. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  108. package/dist/types/common/timing/nav-timing.d.ts.map +1 -1
  109. package/dist/types/common/wrap/index.d.ts +1 -2
  110. package/dist/types/common/wrap/index.d.ts.map +1 -1
  111. package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
  112. package/dist/types/common/wrap/wrap-function.d.ts +0 -1
  113. package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
  114. package/dist/types/common/wrap/wrap-promise.d.ts.map +1 -1
  115. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  116. package/dist/types/features/jserrors/aggregate/index.d.ts +4 -3
  117. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  118. package/dist/types/features/page_view_event/aggregate/initialized-features.d.ts.map +1 -1
  119. package/dist/types/features/session_replay/aggregate/index.d.ts +1 -1
  120. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  121. package/dist/types/features/session_replay/constants.d.ts +4 -0
  122. package/dist/types/features/session_replay/constants.d.ts.map +1 -1
  123. package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
  124. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  125. package/dist/types/features/session_replay/shared/stylesheet-evaluator.d.ts.map +1 -1
  126. package/dist/types/features/session_replay/shared/utils.d.ts +4 -0
  127. package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -0
  128. package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts +19 -0
  129. package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts.map +1 -0
  130. package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts +16 -0
  131. package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts.map +1 -0
  132. package/dist/types/features/soft_navigations/aggregate/index.d.ts +36 -0
  133. package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -0
  134. package/dist/types/features/soft_navigations/aggregate/initial-page-load-interaction.d.ts +12 -0
  135. package/dist/types/features/soft_navigations/aggregate/initial-page-load-interaction.d.ts.map +1 -0
  136. package/dist/types/features/soft_navigations/aggregate/interaction.d.ts +50 -0
  137. package/dist/types/features/soft_navigations/aggregate/interaction.d.ts.map +1 -0
  138. package/dist/types/features/soft_navigations/constants.d.ts +20 -0
  139. package/dist/types/features/soft_navigations/constants.d.ts.map +1 -0
  140. package/dist/types/features/soft_navigations/index.d.ts +2 -0
  141. package/dist/types/features/soft_navigations/index.d.ts.map +1 -0
  142. package/dist/types/features/soft_navigations/instrument/index.d.ts +7 -0
  143. package/dist/types/features/soft_navigations/instrument/index.d.ts.map +1 -0
  144. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  145. package/dist/types/features/utils/agent-session.d.ts.map +1 -1
  146. package/dist/types/features/utils/instrument-base.d.ts +1 -7
  147. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  148. package/dist/types/features/utils/lazy-feature-loader.d.ts.map +1 -1
  149. package/dist/types/loaders/agent-base.d.ts +5 -1
  150. package/dist/types/loaders/agent-base.d.ts.map +1 -1
  151. package/dist/types/loaders/agent.d.ts +2 -2
  152. package/dist/types/loaders/agent.d.ts.map +1 -1
  153. package/dist/types/loaders/api/api-methods.d.ts +3 -0
  154. package/dist/types/loaders/api/api-methods.d.ts.map +1 -0
  155. package/dist/types/loaders/api/api.d.ts +3 -6
  156. package/dist/types/loaders/api/api.d.ts.map +1 -1
  157. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  158. package/dist/types/loaders/features/features.d.ts +1 -0
  159. package/dist/types/loaders/features/features.d.ts.map +1 -1
  160. package/dist/types/loaders/micro-agent.d.ts +0 -1
  161. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  162. package/package.json +1 -1
  163. package/src/cdn/experimental.js +4 -2
  164. package/src/cdn/spa.js +3 -1
  165. package/src/common/aggregate/aggregator.js +2 -11
  166. package/src/common/config/state/init.js +3 -1
  167. package/src/common/context/observation-context-manager.js +55 -0
  168. package/src/common/event-emitter/contextual-ee.js +20 -10
  169. package/src/common/session/constants.js +1 -0
  170. package/src/common/session/session-entity.js +3 -1
  171. package/src/common/timing/nav-timing.js +7 -3
  172. package/src/common/timing/now.js +1 -1
  173. package/src/common/util/feature-flags.js +1 -1
  174. package/src/common/wrap/index.js +1 -2
  175. package/src/common/wrap/wrap-events.js +3 -3
  176. package/src/common/wrap/wrap-fetch.js +3 -2
  177. package/src/common/wrap/wrap-function.js +4 -6
  178. package/src/common/wrap/wrap-promise.js +3 -2
  179. package/src/features/ajax/aggregate/index.js +36 -18
  180. package/src/features/jserrors/aggregate/index.js +70 -73
  181. package/src/features/page_view_event/aggregate/index.js +1 -1
  182. package/src/features/page_view_event/aggregate/initialized-features.js +1 -0
  183. package/src/features/session_replay/aggregate/index.js +92 -95
  184. package/src/features/session_replay/constants.js +5 -0
  185. package/src/features/session_replay/instrument/index.js +24 -9
  186. package/src/features/session_replay/shared/recorder.js +5 -4
  187. package/src/features/session_replay/shared/stylesheet-evaluator.js +8 -7
  188. package/src/features/session_replay/shared/utils.js +19 -0
  189. package/src/features/soft_navigations/aggregate/ajax-node.js +57 -0
  190. package/src/features/soft_navigations/aggregate/bel-node.js +26 -0
  191. package/src/features/soft_navigations/aggregate/index.js +254 -0
  192. package/src/features/soft_navigations/aggregate/initial-page-load-interaction.js +53 -0
  193. package/src/features/soft_navigations/aggregate/interaction.js +159 -0
  194. package/src/features/soft_navigations/constants.js +29 -0
  195. package/src/features/soft_navigations/index.js +1 -0
  196. package/src/features/soft_navigations/instrument/index.js +67 -0
  197. package/src/features/spa/aggregate/index.js +5 -4
  198. package/src/features/utils/agent-session.js +2 -1
  199. package/src/features/utils/instrument-base.js +7 -10
  200. package/src/features/utils/lazy-feature-loader.js +2 -0
  201. package/src/loaders/agent-base.js +18 -3
  202. package/src/loaders/agent.js +18 -17
  203. package/src/loaders/api/api-methods.js +12 -0
  204. package/src/loaders/api/api.js +17 -28
  205. package/src/loaders/configure/configure.js +4 -1
  206. package/src/loaders/features/enabled-features.js +1 -1
  207. package/src/loaders/features/features.js +3 -1
  208. package/dist/cjs/common/wrap/wrap-raf.js +0 -55
  209. package/dist/esm/common/wrap/wrap-raf.js +0 -48
  210. package/dist/types/common/event-emitter/event-context.d.ts.map +0 -1
  211. package/dist/types/common/wrap/wrap-raf.d.ts +0 -16
  212. package/dist/types/common/wrap/wrap-raf.d.ts.map +0 -1
  213. package/src/common/wrap/wrap-raf.js +0 -52
  214. /package/dist/cjs/common/{event-emitter → context}/event-context.js +0 -0
  215. /package/dist/esm/common/{event-emitter → context}/event-context.js +0 -0
  216. /package/dist/types/common/{event-emitter → context}/event-context.d.ts +0 -0
  217. /package/src/common/{event-emitter → context}/event-context.js +0 -0
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.AjaxNode = void 0;
7
+ var _belSerializer = require("../../../common/serialize/bel-serializer");
8
+ var _constants = require("../constants");
9
+ var _belNode = require("./bel-node");
10
+ class AjaxNode extends _belNode.BelNode {
11
+ constructor(agentIdentifier, ajaxEvent) {
12
+ super(agentIdentifier);
13
+ this.belType = _constants.NODE_TYPE.AJAX;
14
+ this.method = ajaxEvent.method;
15
+ this.status = ajaxEvent.status;
16
+ this.domain = ajaxEvent.domain;
17
+ this.path = ajaxEvent.path;
18
+ this.txSize = ajaxEvent.requestSize;
19
+ this.rxSize = ajaxEvent.responseSize;
20
+ this.requestedWith = ajaxEvent.type === 'fetch' ? 1 : ''; // 'xhr' and 'beacon' types get the empty string
21
+ this.spanId = ajaxEvent.spanId;
22
+ this.traceId = ajaxEvent.traceId;
23
+ this.spanTimestamp = ajaxEvent.spanTimestamp;
24
+ this.gql = ajaxEvent.gql;
25
+ this.start = ajaxEvent.startTime;
26
+ this.end = ajaxEvent.endTime;
27
+ }
28
+ serialize(parentStartTimestamp) {
29
+ const addString = (0, _belSerializer.getAddStringContext)(this.agentIdentifier);
30
+ const nodeList = [];
31
+
32
+ // IMPORTANT: The order in which addString is called matters and correlates to the order in which string shows up in the harvest payload. Do not re-order the following code.
33
+ const fields = [(0, _belSerializer.numeric)(this.belType), 0,
34
+ // this will be overwritten below with number of attached nodes
35
+ (0, _belSerializer.numeric)(this.start - parentStartTimestamp),
36
+ // start relative to parent start (if part of first node in payload) or first parent start
37
+ (0, _belSerializer.numeric)(this.end - this.start),
38
+ // end is relative to start
39
+ (0, _belSerializer.numeric)(this.callbackEnd), (0, _belSerializer.numeric)(this.callbackDuration), addString(this.method), (0, _belSerializer.numeric)(this.status), addString(this.domain), addString(this.path), (0, _belSerializer.numeric)(this.txSize), (0, _belSerializer.numeric)(this.rxSize), this.requestedWith, addString(this.nodeId), (0, _belSerializer.nullable)(this.spanId, addString, true) + (0, _belSerializer.nullable)(this.traceId, addString, true) + (0, _belSerializer.nullable)(this.spanTimestamp, _belSerializer.numeric)];
40
+ let allAttachedNodes = [];
41
+ if (typeof this.gql === 'object') allAttachedNodes = (0, _belSerializer.addCustomAttributes)(this.gql, addString);
42
+ this.children.forEach(node => allAttachedNodes.push(node.serialize())); // no children is expected under ajax nodes at this time
43
+
44
+ fields[1] = (0, _belSerializer.numeric)(allAttachedNodes.length);
45
+ nodeList.push(fields);
46
+ if (allAttachedNodes.length) nodeList.push(allAttachedNodes.join(';'));
47
+ return nodeList.join(';');
48
+ }
49
+ }
50
+ exports.AjaxNode = AjaxNode;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.BelNode = void 0;
7
+ var _now = require("../../../common/timing/now");
8
+ let nodesSeen = 0;
9
+ class BelNode {
10
+ belType;
11
+ /** List of other BelNode derivatives. Each children should be of a subclass that implements its own 'serialize' function. */
12
+ children = [];
13
+ start = (0, _now.now)();
14
+ end;
15
+ callbackEnd = 0;
16
+ callbackDuration = 0;
17
+ nodeId = ++nodesSeen;
18
+ constructor(agentIdentifier) {
19
+ if (!agentIdentifier) throw new Error('Interaction is missing core attributes');
20
+ this.agentIdentifier = agentIdentifier;
21
+ }
22
+ addChild(child) {
23
+ this.children.push(child);
24
+ }
25
+
26
+ /** Virtual fn for stringifying an instance. */
27
+ serialize() {}
28
+ }
29
+ exports.BelNode = BelNode;
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Aggregate = void 0;
7
+ var _config = require("../../../common/config/config");
8
+ var _handle = require("../../../common/event-emitter/handle");
9
+ var _registerHandler = require("../../../common/event-emitter/register-handler");
10
+ var _harvestScheduler = require("../../../common/harvest/harvest-scheduler");
11
+ var _invoke = require("../../../common/util/invoke");
12
+ var _timeToFirstByte = require("../../../common/vitals/time-to-first-byte");
13
+ var _features = require("../../../loaders/features/features");
14
+ var _constants = require("../../metrics/constants");
15
+ var _aggregateBase = require("../../utils/aggregate-base");
16
+ var _constants2 = require("../constants");
17
+ var _ajaxNode = require("./ajax-node");
18
+ var _initialPageLoadInteraction = require("./initial-page-load-interaction");
19
+ var _interaction = require("./interaction");
20
+ class Aggregate extends _aggregateBase.AggregateBase {
21
+ static featureName = _constants2.FEATURE_NAME;
22
+ constructor(agentIdentifier, aggregator, _ref) {
23
+ let {
24
+ domObserver
25
+ } = _ref;
26
+ super(agentIdentifier, aggregator, _constants2.FEATURE_NAME);
27
+ const harvestTimeSeconds = (0, _config.getConfigurationValue)(agentIdentifier, 'soft_navigations.harvestTimeSeconds') || 10;
28
+ this.interactionsToHarvest = [];
29
+ this.interactionsAwaitingRetry = [];
30
+ this.domObserver = domObserver;
31
+ this.scheduler = new _harvestScheduler.HarvestScheduler('events', {
32
+ onFinished: this.onHarvestFinished.bind(this),
33
+ retryDelay: harvestTimeSeconds,
34
+ onUnload: () => this.interactionInProgress?.done() // return any held ajax or jserr events so they can be sent with EoL harvest
35
+ }, {
36
+ agentIdentifier,
37
+ ee: this.ee
38
+ });
39
+ this.scheduler.harvest.on('events', this.onHarvestStarted.bind(this));
40
+ this.initialPageLoadInteraction = new _initialPageLoadInteraction.InitialPageLoadInteraction(agentIdentifier);
41
+ _timeToFirstByte.timeToFirstByte.subscribe(_ref2 => {
42
+ let {
43
+ entries
44
+ } = _ref2;
45
+ const loadEventTime = entries[0].loadEventEnd;
46
+ this.initialPageLoadInteraction.forceSave = true;
47
+ this.initialPageLoadInteraction.done(loadEventTime);
48
+ this.interactionsToHarvest.push(this.initialPageLoadInteraction);
49
+ this.initialPageLoadInteraction = null;
50
+ // Report metric on the initial page load time
51
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['SoftNav/Interaction/InitialPageLoad/Duration/Ms', Math.round(loadEventTime)], undefined, _features.FEATURE_NAMES.metrics, this.ee);
52
+ });
53
+ this.latestRouteSetByApi = null;
54
+ this.interactionInProgress = null; // aside from the "page load" interaction, there can only ever be 1 ongoing at a time
55
+
56
+ this.blocked = false;
57
+ this.waitForFlags(['spa']).then(_ref3 => {
58
+ let [spaOn] = _ref3;
59
+ if (spaOn) this.scheduler.startTimer(harvestTimeSeconds, 0);else this.blocked = true; // if rum response determines that customer lacks entitlements for spa endpoint, this feature shouldn't harvest
60
+ });
61
+
62
+ // By default, a complete UI driven interaction requires event -> URL change -> DOM mod in that exact order.
63
+ (0, _registerHandler.registerHandler)('newUIEvent', event => this.startUIInteraction(event.type, event.timeStamp, event.target), this.featureName, this.ee);
64
+ (0, _registerHandler.registerHandler)('newURL', (timestamp, url) => this.interactionInProgress?.updateHistory(timestamp, url), this.featureName, this.ee);
65
+ (0, _registerHandler.registerHandler)('newDom', timestamp => {
66
+ this.interactionInProgress?.updateDom(timestamp);
67
+ if (this.interactionInProgress?.seenHistoryAndDomChange()) this.interactionInProgress.done();
68
+ }, this.featureName, this.ee);
69
+ this.#registerApiHandlers();
70
+ (0, _registerHandler.registerHandler)('ajax', this.#handleAjaxEvent.bind(this), this.featureName, this.ee);
71
+ (0, _registerHandler.registerHandler)('jserror', this.#handleJserror.bind(this), this.featureName, this.ee);
72
+ this.drain();
73
+ }
74
+ onHarvestStarted(options) {
75
+ if (this.interactionsToHarvest.length === 0 || this.blocked) return;
76
+
77
+ // The payload depacker takes the first ixn of a payload (if there are multiple ixns) and positively offset the subsequent ixns timestamps by that amount.
78
+ // In order to accurately portray the real start & end times of the 2nd & onward ixns, we hence need to negatively offset their start timestamps with that of the 1st ixn.
79
+ let firstIxnStartTime = 0; // the very 1st ixn does not require any offsetting
80
+ const serializedIxnList = [];
81
+ for (const interaction of this.interactionsToHarvest) {
82
+ serializedIxnList.push(interaction.serialize(firstIxnStartTime));
83
+ if (!firstIxnStartTime) firstIxnStartTime = Math.floor(interaction.start);
84
+ }
85
+ const payload = "bel.7;".concat(serializedIxnList.join(';'));
86
+ if (options.retry) this.interactionsAwaitingRetry.push(...this.interactionsToHarvest);
87
+ this.interactionsToHarvest = [];
88
+ return {
89
+ body: {
90
+ e: payload
91
+ }
92
+ };
93
+ }
94
+ onHarvestFinished(result) {
95
+ if (result.sent && result.retry && this.interactionsAwaitingRetry.length > 0) {
96
+ this.interactionsToHarvest = [...this.interactionsAwaitingRetry, ...this.interactionsToHarvest];
97
+ this.interactionsAwaitingRetry = [];
98
+ }
99
+ }
100
+ startUIInteraction(eventName, startedAt, sourceElem) {
101
+ // this is throttled by instrumentation so that it isn't excessively called
102
+ if (this.interactionInProgress?.createdByApi) return; // api-started interactions cannot be disrupted aka cancelled by UI events (and the vice versa applies as well)
103
+ if (this.interactionInProgress?.done() === false) return;
104
+ this.interactionInProgress = new _interaction.Interaction(this.agentIdentifier, eventName, startedAt, this.latestRouteSetByApi);
105
+ if (eventName === 'click') {
106
+ const sourceElemText = getActionText(sourceElem);
107
+ if (sourceElemText) this.interactionInProgress.customAttributes.actionText = sourceElemText;
108
+ }
109
+ this.interactionInProgress.cancellationTimer = setTimeout(() => {
110
+ this.interactionInProgress.done();
111
+ // Report metric on frequency of cancellation due to timeout for UI ixn
112
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['SoftNav/Interaction/TimeOut'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
113
+ }, 30000); // UI ixn are disregarded after 30 seconds if it's not completed by then
114
+ this.setClosureHandlers();
115
+ }
116
+ setClosureHandlers() {
117
+ this.interactionInProgress.on('finished', () => {
118
+ const ref = this.interactionInProgress;
119
+ this.interactionsToHarvest.push(this.interactionInProgress);
120
+ this.interactionInProgress = null;
121
+ this.domObserver.disconnect(); // can stop observing whenever our interaction logic completes a cycle
122
+
123
+ // Report metric on the ixn duration
124
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ["SoftNav/Interaction/".concat(ref.newURL !== ref.oldURL ? 'RouteChange' : 'Custom', "/Duration/Ms"), Math.round(ref.end - ref.start)], undefined, _features.FEATURE_NAMES.metrics, this.ee);
125
+ });
126
+ this.interactionInProgress.on('cancelled', () => {
127
+ this.interactionInProgress = null;
128
+ this.domObserver.disconnect();
129
+ });
130
+ }
131
+
132
+ /**
133
+ * Find the active interaction (current or past) for a given timestamp. Note that historic lookups mostly only go as far back as the last harvest for this feature.
134
+ * Also, the caller should check the status of the interaction returned if found via {@link Interaction.status}, if that's pertinent.
135
+ * TIP: Cancelled (status) interactions are NOT returned!
136
+ * IMPORTANT: Finished interactions are in queue for next harvest! It's highly recommended that consumer logic be synchronous for safe reference.
137
+ * @param {DOMHighResTimeStamp} timestamp
138
+ * @returns An {@link Interaction} or undefined, if no active interaction was found.
139
+ */
140
+ getInteractionFor(timestamp) {
141
+ /* In the sole case wherein there can be two "interactions" overlapping (initialPageLoad + regular route-change),
142
+ the regular interaction should get precedence in being assigned the "active" interaction in regards to our one-at-a-time model.
143
+ */
144
+ if (this.interactionInProgress?.isActiveDuring(timestamp)) return this.interactionInProgress;
145
+ let saveIxn;
146
+ for (let idx = this.interactionsToHarvest.length - 1; idx >= 0; idx--) {
147
+ // reverse search for the latest completed interaction for efficiency
148
+ const finishedInteraction = this.interactionsToHarvest[idx];
149
+ if (finishedInteraction.isActiveDuring(timestamp)) {
150
+ if (finishedInteraction.trigger !== 'initialPageLoad') return finishedInteraction;
151
+ // It's possible that a complete interaction occurs before page is fully loaded, so we need to consider if a route-change ixn may have overlapped this iPL
152
+ else saveIxn = finishedInteraction;
153
+ }
154
+ }
155
+ if (saveIxn) return saveIxn; // if an iPL was determined to be active and no route-change was found active for the same time, then iPL is deemed the one
156
+ if (this.initialPageLoadInteraction?.isActiveDuring(timestamp)) return this.initialPageLoadInteraction; // lowest precedence and also only if it's still in-progress
157
+ // Time must be when no interaction is happening, so return undefined.
158
+ }
159
+
160
+ /**
161
+ * Handles or redirect ajax event based on the interaction, if any, that it's tied to.
162
+ * @param {Object} event see Ajax feature's storeXhr function for object definition
163
+ */
164
+ #handleAjaxEvent(event) {
165
+ const associatedInteraction = this.getInteractionFor(event.startTime);
166
+ if (!associatedInteraction) {
167
+ // no interaction was happening when this ajax started, so give it back to Ajax feature for processing
168
+ (0, _handle.handle)('returnAjax', [event], undefined, _features.FEATURE_NAMES.ajax, this.ee);
169
+ } else {
170
+ if (associatedInteraction.status === _constants2.INTERACTION_STATUS.FIN) processAjax(this.agentIdentifier, event, associatedInteraction); // tack ajax onto the ixn object awaiting harvest
171
+ else {
172
+ // same thing as above, just at a later time -- if the interaction in progress is cancelled, just send the event back to ajax feat unmodified
173
+ associatedInteraction.on('finished', () => processAjax(this.agentIdentifier, event, associatedInteraction));
174
+ associatedInteraction.on('cancelled', () => (0, _handle.handle)('returnAjax', [event], undefined, _features.FEATURE_NAMES.ajax, this.ee));
175
+ }
176
+ }
177
+ function processAjax(agentId, event, parentInteraction) {
178
+ const newNode = new _ajaxNode.AjaxNode(agentId, event);
179
+ parentInteraction.addChild(newNode);
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Decorate the passed-in params obj with properties relating to any associated interaction at the time of the timestamp.
185
+ * @param {Object} params reference to the local var instance in Jserrors feature's storeError
186
+ * @param {DOMHighResTimeStamp} timestamp time the jserror occurred
187
+ */
188
+ #handleJserror(params, timestamp) {
189
+ const associatedInteraction = this.getInteractionFor(timestamp);
190
+ if (!associatedInteraction) return; // do not need to decorate this jserror params
191
+
192
+ // Whether the interaction is in-progress or already finished, the id will let jserror buffer it under its index, until it gets the next step instruction.
193
+ params.browserInteractionId = associatedInteraction.id;
194
+ if (associatedInteraction.status === _constants2.INTERACTION_STATUS.FIN) {
195
+ // This information cannot be relayed back via handle() that flushes buffered errs because this is being called by a jserror's handle() per se and before the err is buffered.
196
+ params._softNavFinished = true; // instead, signal that this err can be processed right away without needing to be buffered aka wait for an in-progress ixn
197
+ params._softNavAttributes = associatedInteraction.customAttributes;
198
+ } else {
199
+ // These callbacks may be added multiple times for an ixn, but just a single run will deal with all jserrors associated with the interaction.
200
+ // As such, be cautious not to use the params object since that's tied to one specific jserror and won't affect the rest of them.
201
+ associatedInteraction.on('finished', (0, _invoke.single)(() => (0, _handle.handle)('softNavFlush', [associatedInteraction.id, true, associatedInteraction.customAttributes], undefined, _features.FEATURE_NAMES.jserrors, this.ee)));
202
+ associatedInteraction.on('cancelled', (0, _invoke.single)(() => (0, _handle.handle)('softNavFlush', [associatedInteraction.id, false, undefined], undefined, _features.FEATURE_NAMES.jserrors, this.ee))); // don't take custom attrs from cancelled ixns
203
+ }
204
+ }
205
+ #registerApiHandlers() {
206
+ const INTERACTION_API = 'api-ixn-';
207
+ const thisClass = this;
208
+ (0, _registerHandler.registerHandler)(INTERACTION_API + 'get', function (time) {
209
+ let {
210
+ waitForEnd
211
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
212
+ // In here, 'this' refers to the EventContext specific to per InteractionHandle instance spawned by each .interaction() api call.
213
+ // Each api call aka IH instance would therefore retain a reference to either the in-progress interaction *at the time of the call* OR a new api-started interaction.
214
+ this.associatedInteraction = thisClass.getInteractionFor(time);
215
+ if (!this.associatedInteraction) {
216
+ // This new api-driven interaction will be the target of any subsequent .interaction() call, until it is closed by EITHER .end() OR the regular seenHistoryAndDomChange process.
217
+ this.associatedInteraction = thisClass.interactionInProgress = new _interaction.Interaction(thisClass.agentIdentifier, _constants2.API_TRIGGER_NAME, time, thisClass.latestRouteSetByApi);
218
+ thisClass.setClosureHandlers();
219
+ }
220
+ if (waitForEnd === true) this.associatedInteraction.keepOpenUntilEndApi = true;
221
+ }, thisClass.featureName, thisClass.ee);
222
+ (0, _registerHandler.registerHandler)(INTERACTION_API + 'end', function (timeNow) {
223
+ this.associatedInteraction.done(timeNow);
224
+ }, thisClass.featureName, thisClass.ee);
225
+ (0, _registerHandler.registerHandler)(INTERACTION_API + 'save', function () {
226
+ this.associatedInteraction.forceSave = true;
227
+ }, thisClass.featureName, thisClass.ee);
228
+ (0, _registerHandler.registerHandler)(INTERACTION_API + 'ignore', function () {
229
+ this.associatedInteraction.forceIgnore = true;
230
+ }, thisClass.featureName, thisClass.ee);
231
+ (0, _registerHandler.registerHandler)(INTERACTION_API + 'getContext', function (time, callback) {
232
+ if (typeof callback !== 'function') return;
233
+ setTimeout(() => callback(this.associatedInteraction.customDataByApi), 0);
234
+ }, thisClass.featureName, thisClass.ee);
235
+ (0, _registerHandler.registerHandler)(INTERACTION_API + 'onEnd', function (time, callback) {
236
+ if (typeof callback !== 'function') return;
237
+ this.associatedInteraction.onDone.push(callback);
238
+ }, thisClass.featureName, thisClass.ee);
239
+ (0, _registerHandler.registerHandler)(INTERACTION_API + 'actionText', function (time, newActionText) {
240
+ if (newActionText) this.associatedInteraction.customAttributes.actionText = newActionText;
241
+ }, thisClass.featureName, thisClass.ee);
242
+ (0, _registerHandler.registerHandler)(INTERACTION_API + 'setName', function (time, name, trigger) {
243
+ if (name) this.associatedInteraction.customName = name;
244
+ if (trigger) this.associatedInteraction.trigger = trigger;
245
+ }, thisClass.featureName, thisClass.ee);
246
+ (0, _registerHandler.registerHandler)(INTERACTION_API + 'setAttribute', function (time, key, value) {
247
+ this.associatedInteraction.customAttributes[key] = value;
248
+ }, thisClass.featureName, thisClass.ee);
249
+ (0, _registerHandler.registerHandler)(INTERACTION_API + 'routeName', function (time, newRouteName) {
250
+ // notice that this fn tampers with the ixn IP, not with the linked ixn
251
+ thisClass.latestRouteSetByApi = newRouteName;
252
+ if (thisClass.interactionInProgress) thisClass.interactionInProgress.newRoute = newRouteName;
253
+ }, thisClass.featureName, thisClass.ee);
254
+ }
255
+ }
256
+ exports.Aggregate = Aggregate;
257
+ function getActionText(elem) {
258
+ const tagName = elem.tagName.toLowerCase();
259
+ const elementsOfInterest = ['a', 'button', 'input'];
260
+ if (elementsOfInterest.includes(tagName)) {
261
+ return elem.title || elem.value || elem.innerText;
262
+ }
263
+ }
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.InitialPageLoadInteraction = void 0;
7
+ var _navTiming = require("../../../common/timing/nav-timing");
8
+ var _interaction = require("./interaction");
9
+ var _belSerializer = require("../../../common/serialize/bel-serializer");
10
+ var _firstPaint = require("../../../common/vitals/first-paint");
11
+ var _firstContentfulPaint = require("../../../common/vitals/first-contentful-paint");
12
+ var _config = require("../../../common/config/config");
13
+ class InitialPageLoadInteraction extends _interaction.Interaction {
14
+ constructor(agentIdentifier) {
15
+ super(agentIdentifier, 'initialPageLoad', 0, null);
16
+ const agentInfo = (0, _config.getInfo)(agentIdentifier);
17
+ this.queueTime = agentInfo.queueTime;
18
+ this.appTime = agentInfo.applicationTime;
19
+ }
20
+ get firstPaint() {
21
+ return _firstPaint.firstPaint.current.value;
22
+ }
23
+ get firstContentfulPaint() {
24
+ return _firstContentfulPaint.firstContentfulPaint.current.value;
25
+ }
26
+
27
+ /**
28
+ * Build the navTiming node. This assumes the navTimingValues array in nav-timing.js has already been filled with values via the PageViewEvent feature having
29
+ * executed the addPT function first and foremost.
30
+ */
31
+ get navTiming() {
32
+ if (!_navTiming.navTimingValues.length) return;
33
+ /*
34
+ 1. we initialize the seperator to ',' (seperates the nodeType id from the first value)
35
+ 2. we initialize the navTiming node to 'b' (the nodeType id)
36
+ 3. if the value is present, we add the seperator followed by the value;
37
+ otherwise:
38
+ - we add null seperator ('!') to the navTimingNode
39
+ - we set the seperator to an empty string since we already wrote it above
40
+ the reason for writing the null seperator instead of setting the seperator
41
+ is to ensure we still write it if the null is the last navTiming value.
42
+ */
43
+ let seperator = ',';
44
+ let navTimingNode = 'b';
45
+ let prev = 0;
46
+
47
+ // Get all navTiming values except offset aka timeOrigin since we just consider that (this.start) 0.
48
+ // These are the latter 20 of the 21 timings appended by addPT:
49
+ _navTiming.navTimingValues.slice(1, 21).forEach(v => {
50
+ if (v !== undefined) {
51
+ navTimingNode += seperator + (0, _belSerializer.numeric)(v - prev);
52
+ seperator = ',';
53
+ prev = v;
54
+ } else {
55
+ navTimingNode += seperator + '!';
56
+ seperator = '';
57
+ }
58
+ });
59
+ return navTimingNode;
60
+ }
61
+ }
62
+ exports.InitialPageLoadInteraction = InitialPageLoadInteraction;
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Interaction = void 0;
7
+ var _config = require("../../../common/config/config");
8
+ var _runtime = require("../../../common/constants/runtime");
9
+ var _uniqueId = require("../../../common/ids/unique-id");
10
+ var _belSerializer = require("../../../common/serialize/bel-serializer");
11
+ var _cleanUrl = require("../../../common/url/clean-url");
12
+ var _constants = require("../constants");
13
+ var _belNode = require("./bel-node");
14
+ /**
15
+ * link https://github.com/newrelic/nr-querypack/blob/main/schemas/bel/7.qpschema
16
+ **/
17
+ class Interaction extends _belNode.BelNode {
18
+ id = (0, _uniqueId.generateUuid)(); // unique id that is serialized and used to link interactions with errors
19
+ initialPageURL = _runtime.initialLocation;
20
+ oldURL = '' + _runtime.globalScope?.location;
21
+ newURL = '' + _runtime.globalScope?.location;
22
+ customName;
23
+ customAttributes = {};
24
+ customDataByApi = {};
25
+ queueTime; // only used by initialPageLoad interactions
26
+ appTime; // only used by initialPageLoad interactions
27
+ newRoute;
28
+ /** Internal state of this interaction: in-progress, finished, or cancelled. */
29
+ status = _constants.INTERACTION_STATUS.IP;
30
+ domTimestamp = 0;
31
+ historyTimestamp = 0;
32
+ createdByApi = false;
33
+ keepOpenUntilEndApi = false;
34
+ onDone = [];
35
+ cancellationTimer;
36
+ constructor(agentIdentifier, uiEvent, uiEventTimestamp, currentRouteKnown) {
37
+ super(agentIdentifier);
38
+ this.belType = _constants.NODE_TYPE.INTERACTION;
39
+ this.trigger = uiEvent;
40
+ this.start = uiEventTimestamp;
41
+ this.oldRoute = currentRouteKnown;
42
+ this.eventSubscription = new Map([['finished', []], ['cancelled', []]]);
43
+ this.forceSave = this.forceIgnore = false;
44
+ if (this.trigger === _constants.API_TRIGGER_NAME) this.createdByApi = true;
45
+ }
46
+ updateDom(timestamp) {
47
+ this.domTimestamp = timestamp || performance.now(); // default timestamp should be precise for accurate isActiveDuring calculations
48
+ }
49
+ updateHistory(timestamp, newUrl) {
50
+ this.newURL = newUrl || '' + _runtime.globalScope?.location;
51
+ this.historyTimestamp = timestamp || performance.now();
52
+ }
53
+ seenHistoryAndDomChange() {
54
+ return this.historyTimestamp > 0 && this.domTimestamp > this.historyTimestamp; // URL must change before DOM does
55
+ }
56
+ on(event, cb) {
57
+ if (!this.eventSubscription.has(event)) throw new Error('Cannot subscribe to non pre-defined events.');
58
+ if (typeof cb !== 'function') throw new Error('Must supply function as callback.');
59
+ this.eventSubscription.get(event).push(cb);
60
+ }
61
+ done(customEndTime) {
62
+ // User could've mark this interaction--regardless UI or api started--as "don't close until .end() is called on it". Only .end provides a timestamp; the default flows do not.
63
+ if (this.keepOpenUntilEndApi && customEndTime === undefined) return false;
64
+ this.onDone.forEach(apiProvidedCb => apiProvidedCb(this.customDataByApi)); // this interaction's .save or .ignore can still be set by these user provided callbacks for example
65
+
66
+ if (this.forceIgnore) this.#cancel(); // .ignore() always has precedence over save actions
67
+ else if (this.seenHistoryAndDomChange()) this.#finish(customEndTime); // then this should've already finished while it was the interactionInProgress, with a natural end time
68
+ else if (this.forceSave) this.#finish(customEndTime || performance.now()); // a manually saved ixn (did not fulfill conditions) must have a specified end time, if one wasn't provided
69
+ else this.#cancel();
70
+ return true;
71
+ }
72
+ #finish() {
73
+ let customEndTime = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
74
+ if (this.status !== _constants.INTERACTION_STATUS.IP) return; // disallow this call if the ixn is already done aka not in-progress
75
+ clearTimeout(this.cancellationTimer);
76
+ this.end = Math.max(this.domTimestamp, this.historyTimestamp, customEndTime);
77
+ this.customAttributes = {
78
+ ...(0, _config.getInfo)(this.agentIdentifier).jsAttributes,
79
+ ...this.customAttributes
80
+ }; // attrs specific to this interaction should have precedence over the general custom attrs
81
+ this.status = _constants.INTERACTION_STATUS.FIN;
82
+
83
+ // Run all the callbacks awaiting this interaction to finish.
84
+ const callbacks = this.eventSubscription.get('finished');
85
+ callbacks.forEach(fn => fn());
86
+ }
87
+ #cancel() {
88
+ if (this.status !== _constants.INTERACTION_STATUS.IP) return; // disallow this call if the ixn is already done aka not in-progress
89
+ clearTimeout(this.cancellationTimer);
90
+ this.status = _constants.INTERACTION_STATUS.CAN;
91
+
92
+ // Run all the callbacks listening to this interaction's potential cancellation.
93
+ const callbacks = this.eventSubscription.get('cancelled');
94
+ callbacks.forEach(fn => fn());
95
+ }
96
+
97
+ /**
98
+ * Given a timestamp, determine if it falls within this interaction's span, i.e. if this was the active interaction during that time.
99
+ * For in-progress interactions, this only compares the time with the start of span. Cancelled interactions are not considered active at all.
100
+ * @param {DOMHighResTimeStamp} timestamp
101
+ * @returns True or false boolean.
102
+ */
103
+ isActiveDuring(timestamp) {
104
+ if (this.status === _constants.INTERACTION_STATUS.IP) return this.start <= timestamp;
105
+ return this.status === _constants.INTERACTION_STATUS.FIN && this.start <= timestamp && this.end >= timestamp;
106
+ }
107
+
108
+ // Following are virtual properties overridden by a subclass:
109
+ get firstPaint() {}
110
+ get firstContentfulPaint() {}
111
+ get navTiming() {}
112
+ serialize(firstStartTimeOfPayload) {
113
+ const addString = (0, _belSerializer.getAddStringContext)(this.agentIdentifier);
114
+ const nodeList = [];
115
+ let ixnType;
116
+ if (this.trigger === 'initialPageLoad') ixnType = _constants.INTERACTION_TYPE.INITIAL_PAGE_LOAD;else if (this.newURL !== this.oldURL) ixnType = _constants.INTERACTION_TYPE.ROUTE_CHANGE;else ixnType = _constants.INTERACTION_TYPE.UNSPECIFIED;
117
+
118
+ // IMPORTANT: The order in which addString is called matters and correlates to the order in which string shows up in the harvest payload. Do not re-order the following code.
119
+ const fields = [(0, _belSerializer.numeric)(this.belType), 0,
120
+ // this will be overwritten below with number of attached nodes
121
+ (0, _belSerializer.numeric)(Math.floor(this.start - firstStartTimeOfPayload)),
122
+ // relative to first node
123
+ (0, _belSerializer.numeric)(Math.floor(this.end - this.start)),
124
+ // end -- relative to start
125
+ (0, _belSerializer.numeric)(this.callbackEnd),
126
+ // cbEnd -- relative to start; not used by BrowserInteraction events
127
+ (0, _belSerializer.numeric)(this.callbackDuration),
128
+ // not relative
129
+ addString(this.trigger), addString((0, _cleanUrl.cleanURL)(this.initialPageURL, true)), addString((0, _cleanUrl.cleanURL)(this.oldURL, true)), addString((0, _cleanUrl.cleanURL)(this.newURL, true)), addString(this.customName), ixnType, (0, _belSerializer.nullable)(this.queueTime, _belSerializer.numeric, true) + (0, _belSerializer.nullable)(this.appTime, _belSerializer.numeric, true) + (0, _belSerializer.nullable)(this.oldRoute, addString, true) + (0, _belSerializer.nullable)(this.newRoute, addString, true) + addString(this.id), addString(this.nodeId), (0, _belSerializer.nullable)(this.firstPaint, _belSerializer.numeric, true) + (0, _belSerializer.nullable)(this.firstContentfulPaint, _belSerializer.numeric)];
130
+ const allAttachedNodes = (0, _belSerializer.addCustomAttributes)(this.customAttributes || {}, addString); // start with all custom attributes
131
+ if ((0, _config.getInfo)(this.agentIdentifier).atts) allAttachedNodes.push('a,' + addString((0, _config.getInfo)(this.agentIdentifier).atts)); // add apm provided attributes
132
+ /* Querypack encoder+decoder quirkiness:
133
+ - If first ixn node of payload is being processed, we use this node's start to offset. (firstStartTime should be 0--or undefined.)
134
+ - Else for subsequent ixn nodes, we use the first ixn node's start to offset. */
135
+ this.children.forEach(node => allAttachedNodes.push(node.serialize(firstStartTimeOfPayload || this.start))); // recursively add the serialized string of every child of this (ixn) bel node
136
+
137
+ fields[1] = (0, _belSerializer.numeric)(allAttachedNodes.length);
138
+ nodeList.push(fields);
139
+ if (allAttachedNodes.length) nodeList.push(allAttachedNodes.join(';'));
140
+ if (this.navTiming) nodeList.push(this.navTiming);else nodeList.push('');
141
+ // nodeList = [<fields array>, <serialized string of all attributes and children>, <serialized nav timing info> || '']
142
+
143
+ return nodeList.join(';');
144
+ }
145
+ }
146
+ exports.Interaction = Interaction;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.NODE_TYPE = exports.INTERACTION_TYPE = exports.INTERACTION_TRIGGERS = exports.INTERACTION_STATUS = exports.FEATURE_NAME = exports.API_TRIGGER_NAME = void 0;
7
+ var _features = require("../../loaders/features/features");
8
+ const INTERACTION_TRIGGERS = exports.INTERACTION_TRIGGERS = ['click',
9
+ // e.g. user clicks link or the page back/forward buttons
10
+ 'keydown',
11
+ // e.g. user presses left and right arrow key to switch between displayed photo gallery
12
+ 'submit' // e.g. user clicks submit butotn or presses enter while editing a form field
13
+ ];
14
+ const API_TRIGGER_NAME = exports.API_TRIGGER_NAME = 'api';
15
+ const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.softNav;
16
+ const INTERACTION_TYPE = exports.INTERACTION_TYPE = {
17
+ INITIAL_PAGE_LOAD: '',
18
+ ROUTE_CHANGE: 1,
19
+ UNSPECIFIED: 2
20
+ };
21
+ const NODE_TYPE = exports.NODE_TYPE = {
22
+ INTERACTION: 1,
23
+ AJAX: 2,
24
+ CUSTOM_END: 3,
25
+ CUSTOM_TRACER: 4
26
+ };
27
+ const INTERACTION_STATUS = exports.INTERACTION_STATUS = {
28
+ IP: 'in progress',
29
+ FIN: 'finished',
30
+ CAN: 'cancelled'
31
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "SoftNav", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _index.Instrument;
10
+ }
11
+ });
12
+ var _index = require("./instrument/index");