@newrelic/browser-agent 1.302.0-rc.9 → 1.303.0-rc.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 (36) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/common/config/runtime.js +9 -0
  3. package/dist/cjs/common/constants/env.cdn.js +1 -1
  4. package/dist/cjs/common/constants/env.npm.js +1 -1
  5. package/dist/cjs/common/harvest/harvester.js +1 -1
  6. package/dist/cjs/common/util/mfe.js +8 -5
  7. package/dist/cjs/features/utils/agent-session.js +0 -8
  8. package/dist/cjs/loaders/api/consent.js +16 -3
  9. package/dist/cjs/loaders/api/register-api-types.js +5 -2
  10. package/dist/cjs/loaders/api/register.js +12 -10
  11. package/dist/esm/common/config/runtime.js +9 -0
  12. package/dist/esm/common/constants/env.cdn.js +1 -1
  13. package/dist/esm/common/constants/env.npm.js +1 -1
  14. package/dist/esm/common/harvest/harvester.js +1 -1
  15. package/dist/esm/common/util/mfe.js +7 -5
  16. package/dist/esm/features/utils/agent-session.js +0 -8
  17. package/dist/esm/loaders/api/consent.js +16 -3
  18. package/dist/esm/loaders/api/register-api-types.js +5 -2
  19. package/dist/esm/loaders/api/register.js +13 -10
  20. package/dist/types/common/config/runtime.d.ts.map +1 -1
  21. package/dist/types/common/util/mfe.d.ts +3 -0
  22. package/dist/types/common/util/mfe.d.ts.map +1 -1
  23. package/dist/types/features/utils/agent-session.d.ts.map +1 -1
  24. package/dist/types/loaders/api/consent.d.ts.map +1 -1
  25. package/dist/types/loaders/api/register-api-types.d.ts +18 -4
  26. package/dist/types/loaders/api/register-api-types.d.ts.map +1 -1
  27. package/dist/types/loaders/api/register.d.ts +0 -16
  28. package/dist/types/loaders/api/register.d.ts.map +1 -1
  29. package/package.json +1 -1
  30. package/src/common/config/runtime.js +10 -0
  31. package/src/common/harvest/harvester.js +1 -1
  32. package/src/common/util/mfe.js +10 -4
  33. package/src/features/utils/agent-session.js +0 -8
  34. package/src/loaders/api/consent.js +16 -3
  35. package/src/loaders/api/register-api-types.js +5 -2
  36. package/src/loaders/api/register.js +13 -10
package/CHANGELOG.md CHANGED
@@ -3,6 +3,26 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.303.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.302.0...v1.303.0) (2025-11-13)
7
+
8
+
9
+ ### Features
10
+
11
+ * Add custom event support to register API ([#1606](https://github.com/newrelic/newrelic-browser-agent/issues/1606)) ([4137dcb](https://github.com/newrelic/newrelic-browser-agent/commit/4137dcbb339642219164d68695b84a8e48fa9b6f))
12
+ * Add measure support to register API ([#1623](https://github.com/newrelic/newrelic-browser-agent/issues/1623)) ([c2785f3](https://github.com/newrelic/newrelic-browser-agent/commit/c2785f39ca9ea1f5b87f3e2cf4fc7e462d6084e7))
13
+ * Add consent API ([#1533](https://github.com/newrelic/newrelic-browser-agent/issues/1533)) ([4e8ad2a](https://github.com/newrelic/newrelic-browser-agent/commit/4e8ad2a6aea34bbaa39b6beb67c3947feee3c01d))
14
+ * Additional validation to prepare agent for MFE registrations ([#1625](https://github.com/newrelic/newrelic-browser-agent/issues/1625)) ([aa8c02f](https://github.com/newrelic/newrelic-browser-agent/commit/aa8c02f966e9c7df5c4e83c911f9342b2183447f))
15
+ * Allow consent API to be invoked without localStorage access ([#1627](https://github.com/newrelic/newrelic-browser-agent/issues/1627)) ([0690a65](https://github.com/newrelic/newrelic-browser-agent/commit/0690a65bcfa35eabe0e83b13c058398746e924b8))
16
+ * Allow nested registrations ([#1616](https://github.com/newrelic/newrelic-browser-agent/issues/1616)) ([74a8d4a](https://github.com/newrelic/newrelic-browser-agent/commit/74a8d4ac745cff33eb15f9469775f85fd2641097))
17
+ * Retry initial connect call ([#1605](https://github.com/newrelic/newrelic-browser-agent/issues/1605)) ([9770132](https://github.com/newrelic/newrelic-browser-agent/commit/9770132209b9fb1320b3f60eedfa932b0fcfa3a4))
18
+ * SMs for browser connect response ([#1611](https://github.com/newrelic/newrelic-browser-agent/issues/1611)) ([29f5bdf](https://github.com/newrelic/newrelic-browser-agent/commit/29f5bdf6fa36020a87e5c0aa443d64ce55722c85))
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * memoize promise context propagation to avoid safari hangs ([#1597](https://github.com/newrelic/newrelic-browser-agent/issues/1597)) ([23cb559](https://github.com/newrelic/newrelic-browser-agent/commit/23cb55993add2eb7e7b14b0d77c6fa3bbb9abcf1))
24
+ * Obfuscate custom attributes for logs added after PVE ([#1622](https://github.com/newrelic/newrelic-browser-agent/issues/1622)) ([f648e3f](https://github.com/newrelic/newrelic-browser-agent/commit/f648e3f1f843913d4c9be6534b0d1e3ba47eb260))
25
+
6
26
  ## [1.302.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.301.0...v1.302.0) (2025-10-24)
7
27
 
8
28
 
@@ -23,9 +23,18 @@ const ReadOnly = {
23
23
  version: _env.VERSION,
24
24
  originTime: _runtime.originTime
25
25
  };
26
+ const hiddenState = {
27
+ consented: false
28
+ };
26
29
  const RuntimeModel = {
27
30
  /** Agent-specific metadata found in the RUM call response. ex. entityGuid */
28
31
  appMetadata: {},
32
+ get consented() {
33
+ return this.session?.state?.consent || hiddenState.consented;
34
+ },
35
+ set consented(value) {
36
+ hiddenState.consented = value;
37
+ },
29
38
  customTransaction: undefined,
30
39
  denyList: undefined,
31
40
  disabled: false,
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.RRWEB_PACKAGE_NAME = exports.D
17
17
  /**
18
18
  * Exposes the version of the agent
19
19
  */
20
- const VERSION = exports.VERSION = "1.302.0-rc.9";
20
+ const VERSION = exports.VERSION = "1.303.0-rc.0";
21
21
 
22
22
  /**
23
23
  * Exposes the build type of the agent
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.RRWEB_PACKAGE_NAME = exports.D
17
17
  /**
18
18
  * Exposes the version of the agent
19
19
  */
20
- const VERSION = exports.VERSION = "1.302.0-rc.9";
20
+ const VERSION = exports.VERSION = "1.303.0-rc.0";
21
21
 
22
22
  /**
23
23
  * Exposes the build type of the agent
@@ -69,7 +69,7 @@ class Harvester {
69
69
  endpointVersion: aggregateInst.harvestEndpointVersion || 1
70
70
  };
71
71
  if (aggregateInst.blocked) return output;
72
- if (this.agentRef.init?.browser_consent_mode?.enabled && !this.agentRef.runtime?.session?.state?.consent) return output;
72
+ if (this.agentRef.init?.browser_consent_mode?.enabled && !this.agentRef.runtime.consented) return output;
73
73
  const submitMethod = (0, _submitData.getSubmitMethod)(localOpts);
74
74
  if (!submitMethod) return output;
75
75
  const shouldRetryOnFail = !localOpts.isFinalHarvest && submitMethod === _submitData.xhr; // always retry all features harvests except for final
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getVersion2Attributes = getVersion2Attributes;
7
+ exports.hasValidValue = hasValidValue;
7
8
  exports.isValidMFETarget = isValidMFETarget;
8
9
  /**
9
10
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
@@ -17,9 +18,14 @@ exports.isValidMFETarget = isValidMFETarget;
17
18
  function isValidMFETarget(target = {}) {
18
19
  return !!(target.id && target.name);
19
20
  }
21
+ function hasValidValue(val) {
22
+ return typeof val === 'string' && val.trim().length < 501 || typeof val === 'number';
23
+ }
20
24
 
21
25
  /**
22
26
  * When given a valid target, returns an object with the MFE payload attributes. Returns an empty object otherwise.
27
+ * @note Field names may change as the schema is finalized
28
+ *
23
29
  * @param {Object} [target] the registered target
24
30
  * @param {AggregateInstance} [aggregateInstance] the aggregate instance calling the method
25
31
  * @returns {{'mfe.id': *, 'mfe.name': String}|{}} returns an empty object if args are not supplied or the aggregate instance is not supporting version 2
@@ -35,11 +41,8 @@ function getVersion2Attributes(target, aggregateInstance) {
35
41
  }
36
42
  return {
37
43
  'mfe.id': target.id,
38
- // these field names may change as the schema is finalized
39
44
  'mfe.name': target.name,
40
- // these field names may change as the schema is finalized
41
- eventSource: 'MicroFrontendBrowserAgent',
42
- // these field names may change as the schema is finalized
43
- 'parent.id': containerAgentEntityGuid
45
+ eventSource: target.eventSource,
46
+ 'parent.id': target.parent?.id || containerAgentEntityGuid
44
47
  };
45
48
  }
@@ -63,14 +63,6 @@ function setupAgentSession(agentRef) {
63
63
  agentRef.runtime.session.write({
64
64
  consent: accept === undefined ? true : accept
65
65
  });
66
-
67
- // call sendRum if it wasn't called yet
68
- agentRef.features.page_view_event.onAggregateImported.then(loaded => {
69
- const pveAgg = agentRef.features.page_view_event.featAggregate;
70
- if (loaded && !pveAgg.sentRum) {
71
- pveAgg.sendRum();
72
- }
73
- });
74
66
  }, 'session', sharedEE);
75
67
  (0, _drain.drain)(agentRef.agentIdentifier, 'session');
76
68
  return agentRef.runtime.session;
@@ -14,11 +14,24 @@ var _console = require("../../common/util/console");
14
14
  */
15
15
 
16
16
  function setupConsentAPI(agent) {
17
- (0, _sharedHandlers.setupAPI)(_constants.CONSENT, function (accept) {
18
- if (accept !== undefined && typeof accept !== 'boolean') {
17
+ (0, _sharedHandlers.setupAPI)(_constants.CONSENT, function (accept = true) {
18
+ if (typeof accept !== 'boolean') {
19
19
  (0, _console.warn)(65, typeof accept);
20
20
  return;
21
21
  }
22
- (0, _handle.handle)(_constants.prefix + _constants.CONSENT, [accept], undefined, 'session', agent.ee);
22
+ /** harvester, by way of "consented" getter, checks session state first, and falls back on runtime state if not available. Set both here */
23
+ (0, _handle.handle)(_constants.prefix + _constants.CONSENT, [accept], undefined, 'session', agent.ee); // sets session state (if available)
24
+ agent.runtime.consented = accept; // sets runtime state
25
+
26
+ /** if consent is granted, attempt to make a PageView event harvest if one has not already been made */
27
+ if (accept) {
28
+ const pveInst = agent.features.page_view_event;
29
+ pveInst.onAggregateImported.then(loaded => {
30
+ const pveAgg = pveInst.featAggregate;
31
+ if (loaded && !pveAgg.sentRum) {
32
+ pveAgg.sendRum();
33
+ }
34
+ });
35
+ }
23
36
  }, agent);
24
37
  }
@@ -13,8 +13,9 @@ exports.default = void 0;
13
13
  * @property {(name: string, attributes?: object) => void} addPageAction - Add a page action for the registered entity.
14
14
  * @property {(message: string, options?: { customAttributes?: object, level?: 'ERROR' | 'TRACE' | 'DEBUG' | 'INFO' | 'WARN'}) => void} log - Capture a log for the registered entity.
15
15
  * @property {(error: Error | string, customAttributes?: object) => void} noticeError - Notice an error for the registered entity.
16
+ * @property {(target: RegisterAPIConstructor) => RegisterAPI} register - Record a custom event for the registered entity.
16
17
  * @property {(eventType: string, attributes?: Object) => void} recordCustomEvent - Record a custom event for the registered entity.
17
- * @property {(eventType: string, options?: {start: number, end: number, duration: number, customAttributes: object}) => {{start: number, end: number, duration: number, customAttributes: object}}} measure - Measures a task that is recorded as a BrowserPerformance event.
18
+ * @property {(eventType: string, options?: {start: number, end: number, duration: number, customAttributes: object}) => ({start: number, end: number, duration: number, customAttributes: object})} measure - Measures a task that is recorded as a BrowserPerformance event.
18
19
  * @property {(value: string | null) => void} setApplicationVersion - Add an application.version attribute to all outgoing data for the registered entity.
19
20
  * @property {(name: string, value: string | number | boolean | null, persist?: boolean) => void} setCustomAttribute - Add a custom attribute to outgoing data for the registered entity.
20
21
  * @property {(value: string | null) => void} setUserId - Add an enduser.id attribute to all outgoing API data for the registered entity.
@@ -24,13 +25,15 @@ exports.default = void 0;
24
25
  * @typedef {Object} RegisterAPIConstructor
25
26
  * @property {string|number} id - The unique id for the registered entity. This will be assigned to any synthesized entities.
26
27
  * @property {string} name - The readable name for the registered entity. This will be assigned to any synthesized entities.
28
+ * @property {string} [parentId] - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
27
29
  */
28
30
  /**
29
31
  * @typedef {Object} RegisterAPIMetadata
30
32
  * @property {Object} customAttributes - The custom attributes for the registered entity.
31
33
  * @property {Object} target - The options for the registered entity.
32
- * @property {string} target.licenseKey - The license key for the registered entity. If none was supplied, it will assume the license key from the main agent.
34
+ * @property {string} [target.licenseKey] - The license key for the registered entity. If none was supplied, it will assume the license key from the main agent.
33
35
  * @property {string} target.id - The ID for the registered entity.
34
36
  * @property {string} target.name - The name returned for the registered entity.
37
+ * @property {string} [target.parentId] - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
35
38
  */
36
39
  var _default = exports.default = {};
@@ -3,7 +3,6 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.buildRegisterApi = buildRegisterApi;
7
6
  exports.setupRegisterAPI = setupRegisterAPI;
8
7
  var _handle = require("../../common/event-emitter/handle");
9
8
  var _console = require("../../common/util/console");
@@ -35,7 +34,7 @@ var _recordCustomEvent = require("./recordCustomEvent");
35
34
  */
36
35
  function setupRegisterAPI(agent) {
37
36
  (0, _sharedHandlers.setupAPI)(_constants2.REGISTER, function (target) {
38
- return buildRegisterApi(agent, target);
37
+ return register(agent, target);
39
38
  }, agent);
40
39
  }
41
40
 
@@ -43,19 +42,18 @@ function setupRegisterAPI(agent) {
43
42
  * Builds the api object that will be returned from the register api method.
44
43
  * Also conducts certain side-effects, such as harvesting a PageView event when triggered and gathering metadata for the registered entity.
45
44
  * @param {Object} agentRef the reference to the base agent instance
46
- * @param {Object} handlers the shared handlers to be used by both the base agent's API and the external target's API
47
- * @param {Object} target the target information to be used by the external target's API to send data to the correct location
48
- * @param {string} [target.licenseKey] the license key of the target to report data to
49
- * @param {string} target.id the entity ID of the target to report data to
50
- * @param {string} target.name the entity name of the target to report data to
45
+ * @param {import('./register-api-types').RegisterAPIConstructor} target
46
+ * @param {import('./register-api-types').RegisterAPIConstructor} [parent]
51
47
  * @returns {RegisterAPI} the api object to be returned from the register api method
52
48
  */
53
- function buildRegisterApi(agentRef, target) {
49
+ function register(agentRef, target, parent) {
54
50
  const attrs = {};
55
51
  (0, _console.warn)(54, 'newrelic.register');
56
52
  target ||= {};
53
+ target.eventSource = 'MicroFrontendBrowserAgent';
57
54
  target.licenseKey ||= agentRef.info.licenseKey; // will inherit the license key from the container agent if not provided for brevity. A future state may dictate that we need different license keys to do different things.
58
55
  target.blocked = false;
56
+ target.parent = parent || {};
59
57
 
60
58
  /** @type {Function} a function that is set and reports when APIs are triggered -- warns the customer of the invalid state */
61
59
  let invalidApiResponse = () => {};
@@ -88,6 +86,9 @@ function buildRegisterApi(agentRef, target) {
88
86
  /** primary cases that can block the register API from working at init time */
89
87
  if (!agentRef.init.api.allow_registered_children) block((0, _invoke.single)(() => (0, _console.warn)(55)));
90
88
  if (!(0, _mfe.isValidMFETarget)(target)) block((0, _invoke.single)(() => (0, _console.warn)(48, target)));
89
+ if (!(0, _mfe.hasValidValue)(target.id) || !(0, _mfe.hasValidValue)(target.name)) {
90
+ block((0, _invoke.single)(() => (0, _console.warn)(48, target)));
91
+ }
91
92
 
92
93
  /** @type {RegisterAPI} */
93
94
  const api = {
@@ -113,6 +114,7 @@ function buildRegisterApi(agentRef, target) {
113
114
  ...attrs,
114
115
  ...attributes
115
116
  }, agentRef], target),
117
+ register: (target = {}) => report(register, [agentRef, target], api.metadata.target),
116
118
  recordCustomEvent: (eventType, attributes = {}) => report(_recordCustomEvent.recordCustomEvent, [eventType, {
117
119
  ...attrs,
118
120
  ...attributes
@@ -164,8 +166,8 @@ function buildRegisterApi(agentRef, target) {
164
166
  const timestamp = (0, _now.now)();
165
167
  (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ["API/register/".concat(methodToCall.name, "/called")], undefined, _features.FEATURE_NAMES.metrics, agentRef.ee);
166
168
  try {
167
- const shouldDuplicate = agentRef.init.api.duplicate_registered_data;
168
- if (shouldDuplicate === true || Array.isArray(shouldDuplicate)) {
169
+ const shouldDuplicate = agentRef.init.api.duplicate_registered_data && methodToCall.name !== 'register';
170
+ if (shouldDuplicate) {
169
171
  // also report to container by providing undefined target
170
172
  methodToCall(...args, undefined, timestamp);
171
173
  }
@@ -17,9 +17,18 @@ const ReadOnly = {
17
17
  version: VERSION,
18
18
  originTime
19
19
  };
20
+ const hiddenState = {
21
+ consented: false
22
+ };
20
23
  const RuntimeModel = {
21
24
  /** Agent-specific metadata found in the RUM call response. ex. entityGuid */
22
25
  appMetadata: {},
26
+ get consented() {
27
+ return this.session?.state?.consent || hiddenState.consented;
28
+ },
29
+ set consented(value) {
30
+ hiddenState.consented = value;
31
+ },
23
32
  customTransaction: undefined,
24
33
  denyList: undefined,
25
34
  disabled: false,
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.302.0-rc.9";
14
+ export const VERSION = "1.303.0-rc.0";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.302.0-rc.9";
14
+ export const VERSION = "1.303.0-rc.0";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -61,7 +61,7 @@ export class Harvester {
61
61
  endpointVersion: aggregateInst.harvestEndpointVersion || 1
62
62
  };
63
63
  if (aggregateInst.blocked) return output;
64
- if (this.agentRef.init?.browser_consent_mode?.enabled && !this.agentRef.runtime?.session?.state?.consent) return output;
64
+ if (this.agentRef.init?.browser_consent_mode?.enabled && !this.agentRef.runtime.consented) return output;
65
65
  const submitMethod = getSubmitMethod(localOpts);
66
66
  if (!submitMethod) return output;
67
67
  const shouldRetryOnFail = !localOpts.isFinalHarvest && submitMethod === xhrMethod; // always retry all features harvests except for final
@@ -10,9 +10,14 @@
10
10
  export function isValidMFETarget(target = {}) {
11
11
  return !!(target.id && target.name);
12
12
  }
13
+ export function hasValidValue(val) {
14
+ return typeof val === 'string' && val.trim().length < 501 || typeof val === 'number';
15
+ }
13
16
 
14
17
  /**
15
18
  * When given a valid target, returns an object with the MFE payload attributes. Returns an empty object otherwise.
19
+ * @note Field names may change as the schema is finalized
20
+ *
16
21
  * @param {Object} [target] the registered target
17
22
  * @param {AggregateInstance} [aggregateInstance] the aggregate instance calling the method
18
23
  * @returns {{'mfe.id': *, 'mfe.name': String}|{}} returns an empty object if args are not supplied or the aggregate instance is not supporting version 2
@@ -28,11 +33,8 @@ export function getVersion2Attributes(target, aggregateInstance) {
28
33
  }
29
34
  return {
30
35
  'mfe.id': target.id,
31
- // these field names may change as the schema is finalized
32
36
  'mfe.name': target.name,
33
- // these field names may change as the schema is finalized
34
- eventSource: 'MicroFrontendBrowserAgent',
35
- // these field names may change as the schema is finalized
36
- 'parent.id': containerAgentEntityGuid
37
+ eventSource: target.eventSource,
38
+ 'parent.id': target.parent?.id || containerAgentEntityGuid
37
39
  };
38
40
  }
@@ -56,14 +56,6 @@ export function setupAgentSession(agentRef) {
56
56
  agentRef.runtime.session.write({
57
57
  consent: accept === undefined ? true : accept
58
58
  });
59
-
60
- // call sendRum if it wasn't called yet
61
- agentRef.features.page_view_event.onAggregateImported.then(loaded => {
62
- const pveAgg = agentRef.features.page_view_event.featAggregate;
63
- if (loaded && !pveAgg.sentRum) {
64
- pveAgg.sendRum();
65
- }
66
- });
67
59
  }, 'session', sharedEE);
68
60
  drain(agentRef.agentIdentifier, 'session');
69
61
  return agentRef.runtime.session;
@@ -7,11 +7,24 @@ import { setupAPI } from './sharedHandlers';
7
7
  import { handle } from '../../common/event-emitter/handle';
8
8
  import { warn } from '../../common/util/console';
9
9
  export function setupConsentAPI(agent) {
10
- setupAPI(CONSENT, function (accept) {
11
- if (accept !== undefined && typeof accept !== 'boolean') {
10
+ setupAPI(CONSENT, function (accept = true) {
11
+ if (typeof accept !== 'boolean') {
12
12
  warn(65, typeof accept);
13
13
  return;
14
14
  }
15
- handle(prefix + CONSENT, [accept], undefined, 'session', agent.ee);
15
+ /** harvester, by way of "consented" getter, checks session state first, and falls back on runtime state if not available. Set both here */
16
+ handle(prefix + CONSENT, [accept], undefined, 'session', agent.ee); // sets session state (if available)
17
+ agent.runtime.consented = accept; // sets runtime state
18
+
19
+ /** if consent is granted, attempt to make a PageView event harvest if one has not already been made */
20
+ if (accept) {
21
+ const pveInst = agent.features.page_view_event;
22
+ pveInst.onAggregateImported.then(loaded => {
23
+ const pveAgg = pveInst.featAggregate;
24
+ if (loaded && !pveAgg.sentRum) {
25
+ pveAgg.sendRum();
26
+ }
27
+ });
28
+ }
16
29
  }, agent);
17
30
  }
@@ -8,8 +8,9 @@
8
8
  * @property {(name: string, attributes?: object) => void} addPageAction - Add a page action for the registered entity.
9
9
  * @property {(message: string, options?: { customAttributes?: object, level?: 'ERROR' | 'TRACE' | 'DEBUG' | 'INFO' | 'WARN'}) => void} log - Capture a log for the registered entity.
10
10
  * @property {(error: Error | string, customAttributes?: object) => void} noticeError - Notice an error for the registered entity.
11
+ * @property {(target: RegisterAPIConstructor) => RegisterAPI} register - Record a custom event for the registered entity.
11
12
  * @property {(eventType: string, attributes?: Object) => void} recordCustomEvent - Record a custom event for the registered entity.
12
- * @property {(eventType: string, options?: {start: number, end: number, duration: number, customAttributes: object}) => {{start: number, end: number, duration: number, customAttributes: object}}} measure - Measures a task that is recorded as a BrowserPerformance event.
13
+ * @property {(eventType: string, options?: {start: number, end: number, duration: number, customAttributes: object}) => ({start: number, end: number, duration: number, customAttributes: object})} measure - Measures a task that is recorded as a BrowserPerformance event.
13
14
  * @property {(value: string | null) => void} setApplicationVersion - Add an application.version attribute to all outgoing data for the registered entity.
14
15
  * @property {(name: string, value: string | number | boolean | null, persist?: boolean) => void} setCustomAttribute - Add a custom attribute to outgoing data for the registered entity.
15
16
  * @property {(value: string | null) => void} setUserId - Add an enduser.id attribute to all outgoing API data for the registered entity.
@@ -20,15 +21,17 @@
20
21
  * @typedef {Object} RegisterAPIConstructor
21
22
  * @property {string|number} id - The unique id for the registered entity. This will be assigned to any synthesized entities.
22
23
  * @property {string} name - The readable name for the registered entity. This will be assigned to any synthesized entities.
24
+ * @property {string} [parentId] - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
23
25
  */
24
26
 
25
27
  /**
26
28
  * @typedef {Object} RegisterAPIMetadata
27
29
  * @property {Object} customAttributes - The custom attributes for the registered entity.
28
30
  * @property {Object} target - The options for the registered entity.
29
- * @property {string} target.licenseKey - The license key for the registered entity. If none was supplied, it will assume the license key from the main agent.
31
+ * @property {string} [target.licenseKey] - The license key for the registered entity. If none was supplied, it will assume the license key from the main agent.
30
32
  * @property {string} target.id - The ID for the registered entity.
31
33
  * @property {string} target.name - The name returned for the registered entity.
34
+ * @property {string} [target.parentId] - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
32
35
  */
33
36
 
34
37
  export default {};
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { handle } from '../../common/event-emitter/handle';
6
6
  import { warn } from '../../common/util/console';
7
- import { isValidMFETarget } from '../../common/util/mfe';
7
+ import { hasValidValue, isValidMFETarget } from '../../common/util/mfe';
8
8
  import { FEATURE_NAMES } from '../features/features';
9
9
  import { now } from '../../common/timing/now';
10
10
  import { SUPPORTABILITY_METRIC_CHANNEL } from '../../features/metrics/constants';
@@ -28,7 +28,7 @@ import { recordCustomEvent } from './recordCustomEvent';
28
28
  */
29
29
  export function setupRegisterAPI(agent) {
30
30
  setupAPI(REGISTER, function (target) {
31
- return buildRegisterApi(agent, target);
31
+ return register(agent, target);
32
32
  }, agent);
33
33
  }
34
34
 
@@ -36,19 +36,18 @@ export function setupRegisterAPI(agent) {
36
36
  * Builds the api object that will be returned from the register api method.
37
37
  * Also conducts certain side-effects, such as harvesting a PageView event when triggered and gathering metadata for the registered entity.
38
38
  * @param {Object} agentRef the reference to the base agent instance
39
- * @param {Object} handlers the shared handlers to be used by both the base agent's API and the external target's API
40
- * @param {Object} target the target information to be used by the external target's API to send data to the correct location
41
- * @param {string} [target.licenseKey] the license key of the target to report data to
42
- * @param {string} target.id the entity ID of the target to report data to
43
- * @param {string} target.name the entity name of the target to report data to
39
+ * @param {import('./register-api-types').RegisterAPIConstructor} target
40
+ * @param {import('./register-api-types').RegisterAPIConstructor} [parent]
44
41
  * @returns {RegisterAPI} the api object to be returned from the register api method
45
42
  */
46
- export function buildRegisterApi(agentRef, target) {
43
+ function register(agentRef, target, parent) {
47
44
  const attrs = {};
48
45
  warn(54, 'newrelic.register');
49
46
  target ||= {};
47
+ target.eventSource = 'MicroFrontendBrowserAgent';
50
48
  target.licenseKey ||= agentRef.info.licenseKey; // will inherit the license key from the container agent if not provided for brevity. A future state may dictate that we need different license keys to do different things.
51
49
  target.blocked = false;
50
+ target.parent = parent || {};
52
51
 
53
52
  /** @type {Function} a function that is set and reports when APIs are triggered -- warns the customer of the invalid state */
54
53
  let invalidApiResponse = () => {};
@@ -81,6 +80,9 @@ export function buildRegisterApi(agentRef, target) {
81
80
  /** primary cases that can block the register API from working at init time */
82
81
  if (!agentRef.init.api.allow_registered_children) block(single(() => warn(55)));
83
82
  if (!isValidMFETarget(target)) block(single(() => warn(48, target)));
83
+ if (!hasValidValue(target.id) || !hasValidValue(target.name)) {
84
+ block(single(() => warn(48, target)));
85
+ }
84
86
 
85
87
  /** @type {RegisterAPI} */
86
88
  const api = {
@@ -106,6 +108,7 @@ export function buildRegisterApi(agentRef, target) {
106
108
  ...attrs,
107
109
  ...attributes
108
110
  }, agentRef], target),
111
+ register: (target = {}) => report(register, [agentRef, target], api.metadata.target),
109
112
  recordCustomEvent: (eventType, attributes = {}) => report(recordCustomEvent, [eventType, {
110
113
  ...attrs,
111
114
  ...attributes
@@ -157,8 +160,8 @@ export function buildRegisterApi(agentRef, target) {
157
160
  const timestamp = now();
158
161
  handle(SUPPORTABILITY_METRIC_CHANNEL, ["API/register/".concat(methodToCall.name, "/called")], undefined, FEATURE_NAMES.metrics, agentRef.ee);
159
162
  try {
160
- const shouldDuplicate = agentRef.init.api.duplicate_registered_data;
161
- if (shouldDuplicate === true || Array.isArray(shouldDuplicate)) {
163
+ const shouldDuplicate = agentRef.init.api.duplicate_registered_data && methodToCall.name !== 'register';
164
+ if (shouldDuplicate) {
162
165
  // also report to container by providing undefined target
163
166
  methodToCall(...args, undefined, timestamp);
164
167
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/common/config/runtime.js"],"names":[],"mappings":"AA4CO,gDAON"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/common/config/runtime.js"],"names":[],"mappings":"AAsDO,gDAON"}
@@ -7,8 +7,11 @@
7
7
  * @returns {boolean}
8
8
  */
9
9
  export function isValidMFETarget(target?: Object): boolean;
10
+ export function hasValidValue(val: any): boolean;
10
11
  /**
11
12
  * When given a valid target, returns an object with the MFE payload attributes. Returns an empty object otherwise.
13
+ * @note Field names may change as the schema is finalized
14
+ *
12
15
  * @param {Object} [target] the registered target
13
16
  * @param {AggregateInstance} [aggregateInstance] the aggregate instance calling the method
14
17
  * @returns {{'mfe.id': *, 'mfe.name': String}|{}} returns an empty object if args are not supplied or the aggregate instance is not supporting version 2
@@ -1 +1 @@
1
- {"version":3,"file":"mfe.d.ts","sourceRoot":"","sources":["../../../../src/common/util/mfe.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,0CAHW,MAAM,GACJ,OAAO,CAInB;AAED;;;;;GAKG;AACH,+CAJW,MAAM,sBACN,iBAAiB,GACf;IAAC,QAAQ,EAAE,GAAC,CAAC;IAAC,UAAU,SAAQ;CAAC,GAAC,EAAE,CAiBhD"}
1
+ {"version":3,"file":"mfe.d.ts","sourceRoot":"","sources":["../../../../src/common/util/mfe.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,0CAHW,MAAM,GACJ,OAAO,CAInB;AAED,iDAEC;AAED;;;;;;;GAOG;AACH,+CAJW,MAAM,sBACN,iBAAiB,GACf;IAAC,QAAQ,EAAE,GAAC,CAAC;IAAC,UAAU,SAAQ;CAAC,GAAC,EAAE,CAiBhD"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/agent-session.js"],"names":[],"mappings":"AAaA,sDA4DC"}
1
+ {"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/agent-session.js"],"names":[],"mappings":"AAaA,sDAoDC"}
@@ -1 +1 @@
1
- {"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/consent.js"],"names":[],"mappings":"AASA,kDAQC"}
1
+ {"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/consent.js"],"names":[],"mappings":"AASA,kDAqBC"}
@@ -16,19 +16,28 @@ export type RegisterAPI = {
16
16
  * - Notice an error for the registered entity.
17
17
  */
18
18
  noticeError: (error: Error | string, customAttributes?: object) => void;
19
+ /**
20
+ * - Record a custom event for the registered entity.
21
+ */
22
+ register: (target: RegisterAPIConstructor) => RegisterAPI;
19
23
  /**
20
24
  * - Record a custom event for the registered entity.
21
25
  */
22
26
  recordCustomEvent: (eventType: string, attributes?: Object) => void;
23
27
  /**
24
- * {start: number, end: number, duration: number, customAttributes: object}}} measure - Measures a task that is recorded as a BrowserPerformance event.
28
+ * - Measures a task that is recorded as a BrowserPerformance event.
25
29
  */
26
- "": (eventType: string, options?: {
30
+ measure: (eventType: string, options?: {
27
31
  start: number;
28
32
  end: number;
29
33
  duration: number;
30
34
  customAttributes: object;
31
- }) => {};
35
+ }) => ({
36
+ start: number;
37
+ end: number;
38
+ duration: number;
39
+ customAttributes: object;
40
+ });
32
41
  /**
33
42
  * - Add an application.version attribute to all outgoing data for the registered entity.
34
43
  */
@@ -55,6 +64,10 @@ export type RegisterAPIConstructor = {
55
64
  * - The readable name for the registered entity. This will be assigned to any synthesized entities.
56
65
  */
57
66
  name: string;
67
+ /**
68
+ * - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
69
+ */
70
+ parentId?: string | undefined;
58
71
  };
59
72
  export type RegisterAPIMetadata = {
60
73
  /**
@@ -65,9 +78,10 @@ export type RegisterAPIMetadata = {
65
78
  * - The options for the registered entity.
66
79
  */
67
80
  target: {
68
- licenseKey: string;
81
+ licenseKey?: string | undefined;
69
82
  id: string;
70
83
  name: string;
84
+ parentId?: string | undefined;
71
85
  };
72
86
  };
73
87
  //# sourceMappingURL=register-api-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"register-api-types.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/register-api-types.js"],"names":[],"mappings":";;;;;;mBAOc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI;;;;SAC3C,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;KAAC,KAAK,IAAI;;;;iBACxH,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,KAAK,IAAI;;;;uBAC1D,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI;;;;QAChD,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAC,KAAK,EAAC;;;;2BAC5G,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI;;;;wBAC9B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI;;;;eAClF,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI;;;;cAC9B,mBAAmB;;;;;;QAKnB,MAAM,GAAC,MAAM;;;;UACb,MAAM;;;;;;sBAKN,MAAM;;;;YAEjB;QAA0B,UAAU,EAAzB,MAAM;QACS,EAAE,EAAjB,MAAM;QACS,IAAI,EAAnB,MAAM;KACnB"}
1
+ {"version":3,"file":"register-api-types.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/register-api-types.js"],"names":[],"mappings":";;;;;;mBAOc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI;;;;SAC3C,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;KAAC,KAAK,IAAI;;;;iBACxH,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,KAAK,IAAI;;;;cAC1D,CAAC,MAAM,EAAE,sBAAsB,KAAK,WAAW;;;;uBAC/C,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI;;;;aAChD,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAC,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAC,CAAC;;;;2BACrL,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI;;;;wBAC9B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI;;;;eAClF,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI;;;;cAC9B,mBAAmB;;;;;;QAKnB,MAAM,GAAC,MAAM;;;;UACb,MAAM;;;;;;;;;;sBAMN,MAAM;;;;YAEjB;QAA2B,UAAU;QACX,EAAE,EAAjB,MAAM;QACS,IAAI,EAAnB,MAAM;QACU,QAAQ;KACrC"}
@@ -7,21 +7,5 @@
7
7
  * It is not recommended for use in production environments and will not receive support for issues.
8
8
  */
9
9
  export function setupRegisterAPI(agent: any): void;
10
- /**
11
- * Builds the api object that will be returned from the register api method.
12
- * Also conducts certain side-effects, such as harvesting a PageView event when triggered and gathering metadata for the registered entity.
13
- * @param {Object} agentRef the reference to the base agent instance
14
- * @param {Object} handlers the shared handlers to be used by both the base agent's API and the external target's API
15
- * @param {Object} target the target information to be used by the external target's API to send data to the correct location
16
- * @param {string} [target.licenseKey] the license key of the target to report data to
17
- * @param {string} target.id the entity ID of the target to report data to
18
- * @param {string} target.name the entity name of the target to report data to
19
- * @returns {RegisterAPI} the api object to be returned from the register api method
20
- */
21
- export function buildRegisterApi(agentRef: Object, target: {
22
- licenseKey?: string | undefined;
23
- id: string;
24
- name: string;
25
- }): RegisterAPI;
26
10
  export type RegisterAPI = import("./register-api-types").RegisterAPI;
27
11
  //# sourceMappingURL=register.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/register.js"],"names":[],"mappings":"AAmBA;;GAEG;AAEH;;;;GAIG;AACH,mDAIC;AAED;;;;;;;;;;GAUG;AACH,2CARW,MAAM,UAGd;IAAwB,UAAU;IACX,EAAE,EAAjB,MAAM;IACS,IAAI,EAAnB,MAAM;CACd,GAAU,WAAW,CAqGvB;0BA5HY,OAAO,sBAAsB,EAAE,WAAW"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/register.js"],"names":[],"mappings":"AAmBA;;GAEG;AAEH;;;;GAIG;AACH,mDAIC;0BAZY,OAAO,sBAAsB,EAAE,WAAW"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.302.0-rc.9",
3
+ "version": "1.303.0-rc.0",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -19,9 +19,19 @@ const ReadOnly = {
19
19
  originTime
20
20
  }
21
21
 
22
+ const hiddenState = {
23
+ consented: false
24
+ }
25
+
22
26
  const RuntimeModel = {
23
27
  /** Agent-specific metadata found in the RUM call response. ex. entityGuid */
24
28
  appMetadata: {},
29
+ get consented () {
30
+ return this.session?.state?.consent || hiddenState.consented
31
+ },
32
+ set consented (value) {
33
+ hiddenState.consented = value
34
+ },
25
35
  customTransaction: undefined,
26
36
  denyList: undefined,
27
37
  disabled: false,
@@ -59,7 +59,7 @@ export class Harvester {
59
59
  triggerHarvestFor (aggregateInst, localOpts = {}) {
60
60
  const output = { ranSend: false, payload: undefined, endpointVersion: aggregateInst.harvestEndpointVersion || 1 }
61
61
  if (aggregateInst.blocked) return output
62
- if (this.agentRef.init?.browser_consent_mode?.enabled && !this.agentRef.runtime?.session?.state?.consent) return output
62
+ if (this.agentRef.init?.browser_consent_mode?.enabled && !this.agentRef.runtime.consented) return output
63
63
 
64
64
  const submitMethod = getSubmitMethod(localOpts)
65
65
  if (!submitMethod) return output
@@ -11,8 +11,14 @@ export function isValidMFETarget (target = {}) {
11
11
  return !!(target.id && target.name)
12
12
  }
13
13
 
14
+ export function hasValidValue (val) {
15
+ return (typeof val === 'string' && val.trim().length < 501) || (typeof val === 'number')
16
+ }
17
+
14
18
  /**
15
19
  * When given a valid target, returns an object with the MFE payload attributes. Returns an empty object otherwise.
20
+ * @note Field names may change as the schema is finalized
21
+ *
16
22
  * @param {Object} [target] the registered target
17
23
  * @param {AggregateInstance} [aggregateInstance] the aggregate instance calling the method
18
24
  * @returns {{'mfe.id': *, 'mfe.name': String}|{}} returns an empty object if args are not supplied or the aggregate instance is not supporting version 2
@@ -27,9 +33,9 @@ export function getVersion2Attributes (target, aggregateInstance) {
27
33
  }
28
34
  }
29
35
  return {
30
- 'mfe.id': target.id, // these field names may change as the schema is finalized
31
- 'mfe.name': target.name, // these field names may change as the schema is finalized
32
- eventSource: 'MicroFrontendBrowserAgent', // these field names may change as the schema is finalized
33
- 'parent.id': containerAgentEntityGuid
36
+ 'mfe.id': target.id,
37
+ 'mfe.name': target.name,
38
+ eventSource: target.eventSource,
39
+ 'parent.id': target.parent?.id || containerAgentEntityGuid
34
40
  }
35
41
  }
@@ -58,14 +58,6 @@ export function setupAgentSession (agentRef) {
58
58
 
59
59
  registerHandler('api-consent', (accept) => {
60
60
  agentRef.runtime.session.write({ consent: accept === undefined ? true : accept })
61
-
62
- // call sendRum if it wasn't called yet
63
- agentRef.features.page_view_event.onAggregateImported.then((loaded) => {
64
- const pveAgg = agentRef.features.page_view_event.featAggregate
65
- if (loaded && !pveAgg.sentRum) {
66
- pveAgg.sendRum()
67
- }
68
- })
69
61
  }, 'session', sharedEE)
70
62
 
71
63
  drain(agentRef.agentIdentifier, 'session')
@@ -8,11 +8,24 @@ import { handle } from '../../common/event-emitter/handle'
8
8
  import { warn } from '../../common/util/console'
9
9
 
10
10
  export function setupConsentAPI (agent) {
11
- setupAPI(CONSENT, function (accept) {
12
- if (accept !== undefined && typeof accept !== 'boolean') {
11
+ setupAPI(CONSENT, function (accept = true) {
12
+ if (typeof accept !== 'boolean') {
13
13
  warn(65, typeof accept)
14
14
  return
15
15
  }
16
- handle(prefix + CONSENT, [accept], undefined, 'session', agent.ee)
16
+ /** harvester, by way of "consented" getter, checks session state first, and falls back on runtime state if not available. Set both here */
17
+ handle(prefix + CONSENT, [accept], undefined, 'session', agent.ee) // sets session state (if available)
18
+ agent.runtime.consented = accept // sets runtime state
19
+
20
+ /** if consent is granted, attempt to make a PageView event harvest if one has not already been made */
21
+ if (accept) {
22
+ const pveInst = agent.features.page_view_event
23
+ pveInst.onAggregateImported.then((loaded) => {
24
+ const pveAgg = pveInst.featAggregate
25
+ if (loaded && !pveAgg.sentRum) {
26
+ pveAgg.sendRum()
27
+ }
28
+ })
29
+ }
17
30
  }, agent)
18
31
  }
@@ -8,8 +8,9 @@
8
8
  * @property {(name: string, attributes?: object) => void} addPageAction - Add a page action for the registered entity.
9
9
  * @property {(message: string, options?: { customAttributes?: object, level?: 'ERROR' | 'TRACE' | 'DEBUG' | 'INFO' | 'WARN'}) => void} log - Capture a log for the registered entity.
10
10
  * @property {(error: Error | string, customAttributes?: object) => void} noticeError - Notice an error for the registered entity.
11
+ * @property {(target: RegisterAPIConstructor) => RegisterAPI} register - Record a custom event for the registered entity.
11
12
  * @property {(eventType: string, attributes?: Object) => void} recordCustomEvent - Record a custom event for the registered entity.
12
- * @property {(eventType: string, options?: {start: number, end: number, duration: number, customAttributes: object}) => {{start: number, end: number, duration: number, customAttributes: object}}} measure - Measures a task that is recorded as a BrowserPerformance event.
13
+ * @property {(eventType: string, options?: {start: number, end: number, duration: number, customAttributes: object}) => ({start: number, end: number, duration: number, customAttributes: object})} measure - Measures a task that is recorded as a BrowserPerformance event.
13
14
  * @property {(value: string | null) => void} setApplicationVersion - Add an application.version attribute to all outgoing data for the registered entity.
14
15
  * @property {(name: string, value: string | number | boolean | null, persist?: boolean) => void} setCustomAttribute - Add a custom attribute to outgoing data for the registered entity.
15
16
  * @property {(value: string | null) => void} setUserId - Add an enduser.id attribute to all outgoing API data for the registered entity.
@@ -20,15 +21,17 @@
20
21
  * @typedef {Object} RegisterAPIConstructor
21
22
  * @property {string|number} id - The unique id for the registered entity. This will be assigned to any synthesized entities.
22
23
  * @property {string} name - The readable name for the registered entity. This will be assigned to any synthesized entities.
24
+ * @property {string} [parentId] - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
23
25
  */
24
26
 
25
27
  /**
26
28
  * @typedef {Object} RegisterAPIMetadata
27
29
  * @property {Object} customAttributes - The custom attributes for the registered entity.
28
30
  * @property {Object} target - The options for the registered entity.
29
- * @property {string} target.licenseKey - The license key for the registered entity. If none was supplied, it will assume the license key from the main agent.
31
+ * @property {string} [target.licenseKey] - The license key for the registered entity. If none was supplied, it will assume the license key from the main agent.
30
32
  * @property {string} target.id - The ID for the registered entity.
31
33
  * @property {string} target.name - The name returned for the registered entity.
34
+ * @property {string} [target.parentId] - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
32
35
  */
33
36
 
34
37
  export default {}
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { handle } from '../../common/event-emitter/handle'
6
6
  import { warn } from '../../common/util/console'
7
- import { isValidMFETarget } from '../../common/util/mfe'
7
+ import { hasValidValue, isValidMFETarget } from '../../common/util/mfe'
8
8
  import { FEATURE_NAMES } from '../features/features'
9
9
  import { now } from '../../common/timing/now'
10
10
  import { SUPPORTABILITY_METRIC_CHANNEL } from '../../features/metrics/constants'
@@ -28,7 +28,7 @@ import { recordCustomEvent } from './recordCustomEvent'
28
28
  */
29
29
  export function setupRegisterAPI (agent) {
30
30
  setupAPI(REGISTER, function (target) {
31
- return buildRegisterApi(agent, target)
31
+ return register(agent, target)
32
32
  }, agent)
33
33
  }
34
34
 
@@ -36,20 +36,19 @@ export function setupRegisterAPI (agent) {
36
36
  * Builds the api object that will be returned from the register api method.
37
37
  * Also conducts certain side-effects, such as harvesting a PageView event when triggered and gathering metadata for the registered entity.
38
38
  * @param {Object} agentRef the reference to the base agent instance
39
- * @param {Object} handlers the shared handlers to be used by both the base agent's API and the external target's API
40
- * @param {Object} target the target information to be used by the external target's API to send data to the correct location
41
- * @param {string} [target.licenseKey] the license key of the target to report data to
42
- * @param {string} target.id the entity ID of the target to report data to
43
- * @param {string} target.name the entity name of the target to report data to
39
+ * @param {import('./register-api-types').RegisterAPIConstructor} target
40
+ * @param {import('./register-api-types').RegisterAPIConstructor} [parent]
44
41
  * @returns {RegisterAPI} the api object to be returned from the register api method
45
42
  */
46
- export function buildRegisterApi (agentRef, target) {
43
+ function register (agentRef, target, parent) {
47
44
  const attrs = {}
48
45
  warn(54, 'newrelic.register')
49
46
 
50
47
  target ||= {}
48
+ target.eventSource = 'MicroFrontendBrowserAgent'
51
49
  target.licenseKey ||= agentRef.info.licenseKey // will inherit the license key from the container agent if not provided for brevity. A future state may dictate that we need different license keys to do different things.
52
50
  target.blocked = false
51
+ target.parent = parent || {}
53
52
 
54
53
  /** @type {Function} a function that is set and reports when APIs are triggered -- warns the customer of the invalid state */
55
54
  let invalidApiResponse = () => {}
@@ -75,6 +74,9 @@ export function buildRegisterApi (agentRef, target) {
75
74
  /** primary cases that can block the register API from working at init time */
76
75
  if (!agentRef.init.api.allow_registered_children) block(single(() => warn(55)))
77
76
  if (!isValidMFETarget(target)) block(single(() => warn(48, target)))
77
+ if (!hasValidValue(target.id) || !hasValidValue(target.name)) {
78
+ block(single(() => warn(48, target)))
79
+ }
78
80
 
79
81
  /** @type {RegisterAPI} */
80
82
  const api = {
@@ -82,6 +84,7 @@ export function buildRegisterApi (agentRef, target) {
82
84
  log: (message, options = {}) => report(log, [message, { ...options, customAttributes: { ...attrs, ...(options.customAttributes || {}) } }, agentRef], target),
83
85
  measure: (name, options = {}) => report(measure, [name, { ...options, customAttributes: { ...attrs, ...(options.customAttributes || {}) } }, agentRef], target),
84
86
  noticeError: (error, attributes = {}) => report(noticeError, [error, { ...attrs, ...attributes }, agentRef], target),
87
+ register: (target = {}) => report(register, [agentRef, target], api.metadata.target),
85
88
  recordCustomEvent: (eventType, attributes = {}) => report(recordCustomEvent, [eventType, { ...attrs, ...attributes }, agentRef], target),
86
89
  setApplicationVersion: (value) => setLocalValue('application.version', value),
87
90
  setCustomAttribute: (key, value) => setLocalValue(key, value),
@@ -130,8 +133,8 @@ export function buildRegisterApi (agentRef, target) {
130
133
  const timestamp = now()
131
134
  handle(SUPPORTABILITY_METRIC_CHANNEL, [`API/register/${methodToCall.name}/called`], undefined, FEATURE_NAMES.metrics, agentRef.ee)
132
135
  try {
133
- const shouldDuplicate = agentRef.init.api.duplicate_registered_data
134
- if (shouldDuplicate === true || Array.isArray(shouldDuplicate)) {
136
+ const shouldDuplicate = agentRef.init.api.duplicate_registered_data && methodToCall.name !== 'register'
137
+ if (shouldDuplicate) {
135
138
  // also report to container by providing undefined target
136
139
  methodToCall(...args, undefined, timestamp)
137
140
  }