@dynatrace/react-native-plugin 2.327.2 → 2.329.1

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 (52) hide show
  1. package/README.md +414 -163
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/dynatrace/android/agent/DynatraceConfigurationModule.kt +48 -0
  4. package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +41 -8
  5. package/android/src/main/java/com/dynatrace/android/agent/DynatraceReactPackage.kt +3 -0
  6. package/android/src/main/java/com/dynatrace/android/agent/DynatraceRuntimeConfigurationStore.kt +14 -0
  7. package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +103 -47
  8. package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +12 -4
  9. package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +15 -5
  10. package/files/default.config.js +7 -0
  11. package/files/plugin-runtime.gradle +7 -17
  12. package/files/plugin.gradle +1 -1
  13. package/instrumentation/DynatraceInstrumentation.js +1 -1
  14. package/instrumentation/libs/react-navigation/ReactNavigation.js +53 -18
  15. package/ios/ConfigurationSubscriber.h +15 -0
  16. package/ios/DynatraceRNBridge.h +4 -0
  17. package/ios/DynatraceRNBridge.mm +125 -29
  18. package/lib/core/Dynatrace.js +8 -11
  19. package/lib/core/configuration/ConfigurationHandler.js +3 -0
  20. package/lib/next/Dynatrace.js +14 -32
  21. package/lib/next/DynatraceEventBus.js +35 -0
  22. package/lib/next/appstart/AppStartObserver.js +2 -3
  23. package/lib/next/configuration/INativeRuntimeConfiguration.js +7 -0
  24. package/lib/next/configuration/RuntimeConfigurationObserver.js +40 -0
  25. package/lib/next/events/EventBuilderUtil.js +7 -0
  26. package/lib/next/events/EventData.js +28 -0
  27. package/lib/next/events/EventPipeline.js +5 -11
  28. package/lib/next/events/ExceptionEventData.js +26 -0
  29. package/lib/next/events/{HttpRequestEventBuilder.js → HttpRequestEventData.js} +28 -52
  30. package/lib/next/events/SessionPropertyEventData.js +22 -0
  31. package/lib/next/events/interface/IBaseEvent.js +2 -0
  32. package/lib/next/events/interface/IEventData.js +2 -0
  33. package/lib/next/events/interface/IExceptionEventData.js +2 -0
  34. package/lib/next/events/interface/IHttpRequestEventData.js +2 -0
  35. package/lib/next/events/interface/ISessionPropertyEventData.js +2 -0
  36. package/lib/next/events/modifier/BaseDataEventModifier.js +1 -3
  37. package/lib/next/events/modifier/EventModifierUtil.js +34 -41
  38. package/lib/next/events/modifier/ModifyEventValidation.js +118 -26
  39. package/lib/next/events/modifier/SendEventValidation.js +53 -22
  40. package/lib/next/events/modifier/StringLengthEventModifier.js +53 -0
  41. package/lib/next/events/spec/EventSpecContstants.js +9 -2
  42. package/package.json +8 -3
  43. package/public.js +9 -3
  44. package/react-native-dynatrace.podspec +1 -1
  45. package/scripts/Config.js +6 -2
  46. package/scripts/LineOffsetAnalyze.js +1 -4
  47. package/scripts/core/LineOffsetAnalyzeCall.js +39 -46
  48. package/src/lib/core/interface/NativeDynatraceBridge.ts +6 -2
  49. package/types.d.ts +388 -158
  50. package/lib/next/events/ViewInfoCreator.js +0 -27
  51. package/lib/next/events/modifier/EventLimitation.js +0 -69
  52. /package/lib/next/events/{IHttpRequestEventBuilder.js → interface/EventProperty.js} +0 -0
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const SendEventValidation_1 = require("./modifier/SendEventValidation");
4
+ const EventModifierUtil_1 = require("./modifier/EventModifierUtil");
5
+ const EventCreator_1 = require("./EventCreator");
6
+ class ExceptionEventData {
7
+ constructor(error) {
8
+ this.rawEventProperties = {};
9
+ this.error = error;
10
+ }
11
+ addEventProperty(key, value) {
12
+ this.rawEventProperties[key] = value;
13
+ return this;
14
+ }
15
+ toJSON() {
16
+ const sanitizedEventProperties = SendEventValidation_1.SendEventValidation.modifyEvent(Object.assign({}, this.rawEventProperties));
17
+ if (sanitizedEventProperties === null) {
18
+ return null;
19
+ }
20
+ const exceptionEvent = Object.assign(Object.assign({}, (0, EventCreator_1.createErrorEvent)(this.error.name, this.error.message, this.error.stack)), sanitizedEventProperties);
21
+ (0, EventModifierUtil_1.flagEventProperties)(exceptionEvent);
22
+ (0, EventModifierUtil_1.addIsApiReported)(exceptionEvent);
23
+ return exceptionEvent;
24
+ }
25
+ }
26
+ exports.default = ExceptionEventData;
@@ -3,16 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
4
4
  const TimestampProvider_1 = require("../provider/TimestampProvider");
5
5
  const SendEventValidation_1 = require("./modifier/SendEventValidation");
6
- const logger = new ConsoleLogger_1.ConsoleLogger('Dynatrace');
7
- class HttpRequestEventBuilder {
6
+ const EventModifierUtil_1 = require("./modifier/EventModifierUtil");
7
+ const EventBuilderUtil_1 = require("./EventBuilderUtil");
8
+ const logger = new ConsoleLogger_1.ConsoleLogger('HttpRequestEventData');
9
+ class HttpRequestEventData {
8
10
  constructor(url, requestMethod) {
9
11
  this.url = url;
10
12
  this.requestMethod = requestMethod;
11
13
  this.duration = 0;
12
14
  this.rawEventProperties = {};
13
15
  this.traceContextHint = "api_unused";
14
- this.hasDroppedCustomProperties = false;
15
- this.hasNfnValues = false;
16
+ this.hasDroppedProperties = false;
16
17
  this.triedToOverwriteDuration = false;
17
18
  this.requestMethod =
18
19
  requestMethod.toUpperCase();
@@ -51,14 +52,13 @@ class HttpRequestEventBuilder {
51
52
  this.rawEventProperties[key] = value;
52
53
  return this;
53
54
  }
54
- build() {
55
- if (!this.hasValidMandatoryAttriutes()) {
56
- logger.debug('HttpRequestEventBuilder dropped invalid event');
55
+ toJSON() {
56
+ if (!this.hasValidMandatoryAttributes()) {
57
+ logger.debug('toJSON(): Dropped invalid event');
57
58
  return null;
58
59
  }
59
60
  this.sanitizeDuration();
60
61
  this.sanitizeStatusCode();
61
- this.sanitizeReasonPhrase();
62
62
  this.sanitizeBytesReceived();
63
63
  this.sanitizeBytesSent();
64
64
  const parsedTraceparentHeader = this.traceparentHeader &&
@@ -67,25 +67,25 @@ class HttpRequestEventBuilder {
67
67
  this.traceContextHint = "invalid";
68
68
  }
69
69
  const hasFailedRequest = this.isStatusCodeError() || !!this.error;
70
- const filteredEventProperties = Object.fromEntries(Object.entries(this.rawEventProperties).filter(this.isEventPropertyKey, this));
71
- const sanitizedEventProperties = SendEventValidation_1.SendEventValidation.modifyEvent(filteredEventProperties);
72
- return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, sanitizedEventProperties), { ["url.full"]: this.url, ["network.protocol.name"]: 'http', ["http.request.method"]: this.requestMethod, ["request.trace_context_hint"]: this.traceContextHint, ["duration"]: this.duration, ["start_time"]: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp() - this.duration }), (this.triedToOverwriteDuration && {
70
+ const sanitizedEventProperties = SendEventValidation_1.SendEventValidation.modifyEvent(this.rawEventProperties);
71
+ (0, EventModifierUtil_1.flagEventProperties)(sanitizedEventProperties);
72
+ return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, sanitizedEventProperties), { ["url.full"]: this.url, ["network.protocol.name"]: 'http', ["http.request.method"]: this.requestMethod, ["request.trace_context_hint"]: this.traceContextHint, ["duration"]: this.duration, ["start_time"]: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp() - this.duration }), (this.triedToOverwriteDuration && {
73
73
  ["dt.support.api.overridden_fields"]: [
74
74
  'duration',
75
75
  ],
76
- })), this.includeIfDefined("http.response.status_code", this.statusCode)), this.includeIfDefined("http.response.reason_phrase", this.reasonPhrase)), this.includeIfDefined("request.bytes_sent", this.bytesSent)), this.includeIfDefined("request.bytes_received", this.bytesReceived)), { ["characteristics.has_request"]: true, ["characteristics.is_api_reported"]: true }), this.includeIfTrue("characteristics.has_failed_request", hasFailedRequest)), this.includeIfTrue("characteristics.has_error", hasFailedRequest)), (this.error !== undefined && Object.assign({ ["characteristics.has_exception"]: true, ["exception.type"]: this.error.name, ["exception.message"]: this.error.message }, this.includeIfDefined("exception.stack_trace", this.error.stack)))), (parsedTraceparentHeader && {
76
+ })), (0, EventBuilderUtil_1.includeIfDefined)("http.response.status_code", this.statusCode)), (0, EventBuilderUtil_1.includeIfDefined)("http.response.reason_phrase", this.reasonPhrase)), (0, EventBuilderUtil_1.includeIfDefined)("request.bytes_sent", this.bytesSent)), (0, EventBuilderUtil_1.includeIfDefined)("request.bytes_received", this.bytesReceived)), { ["characteristics.has_request"]: true, ["characteristics.is_api_reported"]: true }), (0, EventBuilderUtil_1.includeIfTrue)("characteristics.has_failed_request", hasFailedRequest)), (0, EventBuilderUtil_1.includeIfTrue)("characteristics.has_error", hasFailedRequest)), (this.error !== undefined && Object.assign({ ["characteristics.has_exception"]: true, ["exception.type"]: this.error.name, ["exception.message"]: this.error.message }, (0, EventBuilderUtil_1.includeIfDefined)("exception.stack_trace", this.error.stack)))), (parsedTraceparentHeader && {
77
77
  ["trace.id"]: parsedTraceparentHeader.traceId,
78
78
  ["span.id"]: parsedTraceparentHeader.spanId,
79
- })), this.includeIfTrue("dt.support.api.has_dropped_custom_properties", this.hasDroppedCustomProperties)), this.includeIfTrue("dt.support.has_nfn_values", this.hasNfnValues));
79
+ })), (0, EventBuilderUtil_1.includeIfTrue)("dt.support.api.has_dropped_properties", this.hasDroppedProperties));
80
80
  }
81
- hasValidMandatoryAttriutes() {
81
+ hasValidMandatoryAttributes() {
82
82
  let isValid = true;
83
83
  if (this.isInvalidUrl(this.url)) {
84
- logger.debug(`HttpRequestEventBuilder: dropped event since given URL is malformed: ${this.url}`);
84
+ logger.debug(`hasValidMandatoryAttributes(): dropped event since given URL is malformed: ${this.url}`);
85
85
  isValid = false;
86
86
  }
87
- if (!HttpRequestEventBuilder.allowedRequestMethods.includes(this.requestMethod)) {
88
- logger.debug(`HttpRequestEventBuilder: dropped event since given Request Method is invalid: ${this.requestMethod}`);
87
+ if (!HttpRequestEventData.allowedRequestMethods.includes(this.requestMethod)) {
88
+ logger.debug(`hasValidMandatoryAttributes(): dropped event since given Request Method is invalid: ${this.requestMethod}`);
89
89
  isValid = false;
90
90
  }
91
91
  return isValid;
@@ -103,62 +103,39 @@ class HttpRequestEventBuilder {
103
103
  }
104
104
  }
105
105
  sanitizeStatusCode() {
106
- if (this.statusCode == undefined && this.error === undefined) {
106
+ if (this.statusCode === undefined && this.error === undefined) {
107
107
  this.statusCode = 0;
108
108
  }
109
109
  if (this.statusCode && this.statusCode < 0) {
110
- logger.debug('HttpRequestEventBuilder: overriding invalid Status Code with 0');
110
+ logger.debug('HttpRequestEventData: overriding invalid Status Code with 0');
111
111
  this.statusCode = 0;
112
- this.hasDroppedCustomProperties = true;
113
- }
114
- }
115
- sanitizeReasonPhrase() {
116
- if (this.reasonPhrase &&
117
- this.reasonPhrase.length >
118
- HttpRequestEventBuilder.maxReasonPhraseLength) {
119
- logger.debug(`HttpRequestEventBuilder: trimming too long Reason Phrase to a length of ${HttpRequestEventBuilder.maxReasonPhraseLength}`);
120
- this.reasonPhrase = this.reasonPhrase.slice(0, HttpRequestEventBuilder.maxReasonPhraseLength);
112
+ this.hasDroppedProperties = true;
121
113
  }
122
114
  }
123
115
  sanitizeDuration() {
124
- this.hasNfnValues || (this.hasNfnValues = !Number.isFinite(this.duration));
125
116
  if (!Number.isFinite(this.duration) || this.duration < 0) {
126
- logger.debug('HttpRequestEventBuilder: overriding invalid Duration with 0');
117
+ logger.debug('HttpRequestEventData: overriding invalid Duration with 0');
127
118
  this.duration = 0;
128
- this.hasDroppedCustomProperties = true;
119
+ this.hasDroppedProperties = true;
129
120
  }
130
121
  }
131
122
  sanitizeBytesSent() {
132
123
  if (this.bytesSent && this.bytesSent < 0) {
133
- logger.debug(`HttpRequestEventBuilder: dropping invalid value for Bytes Sent: ${this.bytesSent}`);
124
+ logger.debug(`HttpRequestEventData: dropping invalid value for Bytes Sent: ${this.bytesSent}`);
134
125
  this.bytesSent = undefined;
135
- this.hasDroppedCustomProperties = true;
126
+ this.hasDroppedProperties = true;
136
127
  }
137
128
  }
138
129
  sanitizeBytesReceived() {
139
130
  if (this.bytesReceived && this.bytesReceived < 0) {
140
- logger.debug(`HttpRequestEventBuilder: dropping invalid value for Bytes Received: ${this.bytesReceived}`);
131
+ logger.debug(`HttpRequestEventData: dropping invalid value for Bytes Received: ${this.bytesReceived}`);
141
132
  this.bytesReceived = undefined;
142
- this.hasDroppedCustomProperties = true;
133
+ this.hasDroppedProperties = true;
143
134
  }
144
135
  }
145
136
  isStatusCodeError() {
146
137
  return (this.statusCode && 400 <= this.statusCode && this.statusCode <= 599);
147
138
  }
148
- isEventPropertyKey([key, _]) {
149
- if (key.startsWith("event_properties")) {
150
- return true;
151
- }
152
- logger.debug(`HttpRequestEventBuilder: dropped event property '$key' as it did not start with prefix ${"event_properties"}`);
153
- this.hasDroppedCustomProperties = true;
154
- return false;
155
- }
156
- includeIfDefined(key, value) {
157
- return value !== undefined ? { [key]: value } : {};
158
- }
159
- includeIfTrue(key, value) {
160
- return value === true ? { [key]: value } : {};
161
- }
162
139
  parseTraceparent(header) {
163
140
  const traceparentRegex = /^00-([0-9a-f]{32})-([0-9a-f]{16})-0[01]$/;
164
141
  const match = header.match(traceparentRegex);
@@ -181,8 +158,8 @@ class HttpRequestEventBuilder {
181
158
  return /^0*$/.test(str);
182
159
  }
183
160
  }
184
- exports.default = HttpRequestEventBuilder;
185
- HttpRequestEventBuilder.allowedRequestMethods = [
161
+ exports.default = HttpRequestEventData;
162
+ HttpRequestEventData.allowedRequestMethods = [
186
163
  'GET',
187
164
  'HEAD',
188
165
  'POST',
@@ -193,4 +170,3 @@ HttpRequestEventBuilder.allowedRequestMethods = [
193
170
  'TRACE',
194
171
  'PATCH',
195
172
  ];
196
- HttpRequestEventBuilder.maxReasonPhraseLength = 5000;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const SendEventValidation_1 = require("./modifier/SendEventValidation");
4
+ const EventModifierUtil_1 = require("./modifier/EventModifierUtil");
5
+ class SessionPropertyEventData {
6
+ constructor() {
7
+ this.rawSessionProperties = {};
8
+ }
9
+ addSessionProperty(key, value) {
10
+ this.rawSessionProperties[key] = value;
11
+ return this;
12
+ }
13
+ toJSON() {
14
+ const event = SendEventValidation_1.SendSessionPropertyEventValidation.modifyEvent(this.rawSessionProperties);
15
+ if (event != null) {
16
+ event["characteristics.has_session_properties"] = true;
17
+ }
18
+ (0, EventModifierUtil_1.addIsApiReported)(event);
19
+ return event;
20
+ }
21
+ }
22
+ exports.default = SessionPropertyEventData;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -5,8 +5,7 @@ const ConfigurationHandler_1 = require("../../../core/configuration/Configuratio
5
5
  const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
6
6
  const EventModifierUtil_1 = require("./EventModifierUtil");
7
7
  class BaseDataEventModifier {
8
- constructor(viewInfo) {
9
- this.viewInfo = viewInfo;
8
+ constructor() {
10
9
  this.logger = new ConsoleLogger_1.ConsoleLogger('BaseDataEventModifier');
11
10
  }
12
11
  modifyEvent(event) {
@@ -14,7 +13,6 @@ class BaseDataEventModifier {
14
13
  this.logger.debug(`modifyEvent(${JSON.stringify(event)}): Event is null!`);
15
14
  return event;
16
15
  }
17
- Object.assign(event, this.viewInfo);
18
16
  event["dt.rum.event.source.type"] = 'react_native';
19
17
  const bundleName = ConfigurationHandler_1.ConfigurationHandler.getBundleName();
20
18
  if (bundleName !== undefined) {
@@ -1,23 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getReactNativeVersion = exports.containEventPropertiesInArray = exports.addIsApiReported = exports.flagEventProperties = exports.containEventProperties = exports.containSessionProperties = exports.trimStringValuesInObject = exports.trimString = exports.isObject = exports.flattenAdditionalData = void 0;
3
+ exports.isKeyCustomProperty = exports.isNotObject = exports.doesNotExceedKeySize = exports.restrictingValueSize = exports.isKeySyntaxAllowed = exports.getReactNativeVersion = exports.containEventPropertiesInArray = exports.addIsApiReported = exports.flagEventProperties = exports.containEventProperties = exports.containSessionProperties = exports.trimString = exports.isObject = void 0;
4
4
  const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
5
- const MAX_STRING_LENGTH_FOR_VALUES = 5000;
5
+ const EventSpecContstants_1 = require("../spec/EventSpecContstants");
6
6
  const logger = new ConsoleLogger_1.ConsoleLogger('EventModifierUtil');
7
- const flattenAdditionalData = (obj, parent, res = {}) => {
8
- for (const key in obj) {
9
- const propName = parent != null ? parent + '.' + key : key;
10
- const valueOfObject = obj[key];
11
- if ((0, exports.isObject)(valueOfObject)) {
12
- (0, exports.flattenAdditionalData)(valueOfObject, propName, res);
13
- }
14
- else {
15
- res[propName] = obj[key];
16
- }
17
- }
18
- return res;
19
- };
20
- exports.flattenAdditionalData = flattenAdditionalData;
21
7
  const isObject = (obj) => {
22
8
  if (obj === null || typeof obj !== 'object') {
23
9
  return false;
@@ -25,25 +11,17 @@ const isObject = (obj) => {
25
11
  return Object.prototype.toString.call(obj) === '[object Object]';
26
12
  };
27
13
  exports.isObject = isObject;
28
- const trimString = (str, maxLength = MAX_STRING_LENGTH_FOR_VALUES) => {
14
+ const trimString = (key, str, maxLength) => {
29
15
  const stringToTrim = str.toString();
30
16
  if (stringToTrim.length <= maxLength) {
31
17
  return stringToTrim;
32
18
  }
33
19
  else {
20
+ logger.debug(`trimString(): Limiting value of ${key} as maximum value length (${maxLength}) is reached!`);
34
21
  return stringToTrim.substring(0, maxLength);
35
22
  }
36
23
  };
37
24
  exports.trimString = trimString;
38
- const trimStringValuesInObject = (jsonData) => {
39
- for (const key in jsonData) {
40
- if (Object.prototype.hasOwnProperty.call(jsonData, key)) {
41
- jsonData[key] = trimStringValue(jsonData[key]);
42
- }
43
- }
44
- return jsonData;
45
- };
46
- exports.trimStringValuesInObject = trimStringValuesInObject;
47
25
  const containSessionProperties = (jsonData) => {
48
26
  for (const key in jsonData) {
49
27
  if (key.startsWith(`${"session_properties"}.`)) {
@@ -70,7 +48,7 @@ const flagEventProperties = (event) => {
70
48
  };
71
49
  exports.flagEventProperties = flagEventProperties;
72
50
  const addIsApiReported = (event) => {
73
- if (event !== null) {
51
+ if (event != null) {
74
52
  event["characteristics.is_api_reported"] = true;
75
53
  }
76
54
  };
@@ -101,22 +79,37 @@ const getReactNativeVersion = () => {
101
79
  return undefined;
102
80
  };
103
81
  exports.getReactNativeVersion = getReactNativeVersion;
104
- const toVersionString = (v) => `${v.major}.${v.minor}.${v.patch}${v.prerelease ? `-${v.prerelease}` : ''}`;
105
- const trimStringValuesInArray = (arrayData) => {
106
- arrayData.forEach((value, index, array) => {
107
- array[index] = trimStringValue(value);
108
- });
109
- return arrayData;
82
+ const isKeySyntaxAllowed = (entry) => {
83
+ const [key] = entry;
84
+ const rV = EventSpecContstants_1.KEY_NAME_REGEX.test(key);
85
+ if (!rV) {
86
+ logger.debug(`isKeySyntaxAllowed(): Filtering key ${key} as it doesnt fulfill character rules!`);
87
+ }
88
+ return rV;
110
89
  };
111
- const trimStringValue = (data) => {
112
- if (typeof data === 'string') {
113
- return (0, exports.trimString)(data);
90
+ exports.isKeySyntaxAllowed = isKeySyntaxAllowed;
91
+ const restrictingValueSize = (entry) => {
92
+ const [key, value] = entry;
93
+ if (typeof value === 'string' &&
94
+ value.length > EventSpecContstants_1.MAX_CUSTOM_EVENT_VALUE_LENGTH) {
95
+ logger.debug(`restrictingValueSize(): Limiting value of ${key} as maximum value length (${EventSpecContstants_1.MAX_CUSTOM_EVENT_VALUE_LENGTH}) is reached!`);
96
+ entry[1] = value.slice(0, EventSpecContstants_1.MAX_CUSTOM_EVENT_VALUE_LENGTH);
114
97
  }
115
- else if (Array.isArray(data)) {
116
- return trimStringValuesInArray(data);
98
+ };
99
+ exports.restrictingValueSize = restrictingValueSize;
100
+ const doesNotExceedKeySize = ([key]) => {
101
+ if (key.length <= EventSpecContstants_1.MAX_CUSTOM_EVENT_KEY_LENGTH) {
102
+ return true;
117
103
  }
118
- else if ((0, exports.isObject)(data)) {
119
- return (0, exports.trimStringValuesInObject)(data);
104
+ else {
105
+ logger.debug(`doesNotExceedKeySize(): Dropping key ${key} as maximum key length (${EventSpecContstants_1.MAX_CUSTOM_EVENT_KEY_LENGTH}) is reached!`);
106
+ return false;
120
107
  }
121
- return data;
122
108
  };
109
+ exports.doesNotExceedKeySize = doesNotExceedKeySize;
110
+ const isNotObject = ([, val]) => typeof val !== 'object' || val === null;
111
+ exports.isNotObject = isNotObject;
112
+ const isKeyCustomProperty = (key) => key.startsWith("event_properties") ||
113
+ key.startsWith("session_properties");
114
+ exports.isKeyCustomProperty = isKeyCustomProperty;
115
+ const toVersionString = (v) => `${v.major}.${v.minor}.${v.patch}${v.prerelease ? `-${v.prerelease}` : ''}`;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ModifyEventValidation = void 0;
4
4
  const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
5
5
  const EventSpecContstants_1 = require("../spec/EventSpecContstants");
6
- const EventLimitation_1 = require("./EventLimitation");
7
6
  const EventModifierUtil_1 = require("./EventModifierUtil");
8
7
  class ModifyEventValidation {
9
8
  constructor() {
@@ -53,29 +52,31 @@ class ModifyEventValidation {
53
52
  }
54
53
  return event;
55
54
  }
56
- isPropertiesAllowed(key, hasSessionPropertyCharacteristics) {
55
+ isCustomPropertiesAllowed(key, hasSessionPropertyCharacteristics) {
57
56
  if (hasSessionPropertyCharacteristics) {
58
57
  if (key.startsWith(`${"event_properties"}.`)) {
59
58
  this.logger.debug(`isPropertiesAllowed(): Filtering key ${key} as usage of event properties is not allowed!`);
60
- return true;
59
+ return false;
61
60
  }
62
61
  }
63
62
  else {
64
63
  if (key.startsWith(`${"session_properties"}.`)) {
65
64
  this.logger.debug(`isPropertiesAllowed(): Filtering key ${key} as usage of session properties is not allowed!`);
66
- return true;
65
+ return false;
67
66
  }
68
67
  }
69
- return false;
68
+ return true;
70
69
  }
71
- isKeyNameForbidden(key) {
70
+ isKeyNameForbidden(key, isAdded = false) {
72
71
  for (const namespace of EventSpecContstants_1.MODIFY_EVENT_WHITELIST_NAMESPACE) {
73
72
  if (key.startsWith(`${namespace}.`)) {
74
73
  return false;
75
74
  }
76
75
  }
77
- if (EventSpecContstants_1.MODIFY_EVENT_WHITELIST_FIELDS.includes(key)) {
78
- return false;
76
+ if (!isAdded) {
77
+ if (EventSpecContstants_1.MODIFY_EVENT_WHITELIST_FIELDS.includes(key)) {
78
+ return false;
79
+ }
79
80
  }
80
81
  this.logger.debug(`isKeyNameForbidden(): Filtering key ${key} as this field is reserved and must not be overridden!`);
81
82
  return true;
@@ -98,22 +99,16 @@ class ModifyEventValidation {
98
99
  const restoredEntries = this.restoreRemovedEntries(Object.entries(originalEvent), userEnrichedEvent, overriddenKeys);
99
100
  const validAndRestoredEntries = validEntries.concat(restoredEntries);
100
101
  const { baseEntries, addedEntries } = this.determineAddedEntries(originalEvent, validAndRestoredEntries);
101
- const limitedEntries = new EventLimitation_1.EventLimitation().limitEventEntries(addedEntries);
102
+ const limitedAddedEntries = this.validateAddedEntries(addedEntries);
102
103
  if (originalEvent["characteristics.has_event_properties"] === undefined &&
103
- (0, EventModifierUtil_1.containEventPropertiesInArray)(limitedEntries)) {
104
- limitedEntries.push([
104
+ (0, EventModifierUtil_1.containEventPropertiesInArray)(limitedAddedEntries)) {
105
+ limitedAddedEntries.push([
105
106
  "characteristics.has_event_properties",
106
107
  true,
107
108
  ]);
108
109
  }
109
- const finalEntries = baseEntries.concat(limitedEntries);
110
- const sizedEntries = new EventLimitation_1.EventLimitation().limitEventProperties(finalEntries);
111
- if (sizedEntries.length < userEnrichedEventEntries.length) {
112
- sizedEntries.push([
113
- "dt.support.api.has_dropped_custom_properties",
114
- true,
115
- ]);
116
- }
110
+ const finalEntries = baseEntries.concat(limitedAddedEntries);
111
+ const sizedEntries = this.enforcePropertyLimit(finalEntries);
117
112
  if (Array.isArray(overriddenKeys) && overriddenKeys.length > 0) {
118
113
  sizedEntries.push([
119
114
  "dt.support.api.overridden_fields",
@@ -128,31 +123,70 @@ class ModifyEventValidation {
128
123
  }
129
124
  return Object.fromEntries(sizedEntries);
130
125
  }
126
+ determineChangedContent(modifiedJSONEventEntries, originalJSONEvent) {
127
+ const changedEntries = [];
128
+ for (const [prop, value] of modifiedJSONEventEntries) {
129
+ const originalValue = originalJSONEvent[prop];
130
+ if (this.isModified(originalValue, value)) {
131
+ changedEntries.push([prop, value]);
132
+ continue;
133
+ }
134
+ }
135
+ return changedEntries;
136
+ }
131
137
  determineValidEntries(userEnrichedEntries, originalJSONEvent, overriddenKeys) {
132
- const newEntries = [];
138
+ const validEntries = [];
139
+ let droppedCustomProperties = false;
140
+ let droppedProperties = false;
133
141
  for (const [prop, value] of userEnrichedEntries) {
134
142
  const originalValue = originalJSONEvent[prop];
135
143
  if (!this.isModified(originalValue, value)) {
136
- newEntries.push([prop, value]);
144
+ validEntries.push([prop, value]);
137
145
  continue;
138
146
  }
139
- if (this.isPropertiesAllowed(prop, originalJSONEvent["characteristics.has_session_properties"] === true)) {
147
+ if (!this.isCustomPropertiesAllowed(prop, originalJSONEvent["characteristics.has_session_properties"] === true)) {
148
+ droppedCustomProperties = true;
140
149
  continue;
141
150
  }
142
151
  const isNewlyAdded = typeof originalValue === 'undefined';
143
- const isForbiddenKey = this.isKeyNameForbidden(prop);
152
+ const isForbiddenKey = this.isKeyNameForbidden(prop, isNewlyAdded);
144
153
  if (isForbiddenKey) {
145
154
  if (!isNewlyAdded) {
146
- newEntries.push([prop, originalValue]);
155
+ validEntries.push([prop, originalValue]);
156
+ }
157
+ else {
158
+ droppedProperties = true;
147
159
  }
148
160
  continue;
149
161
  }
150
162
  if (!isNewlyAdded && !overriddenKeys.includes(prop)) {
151
163
  overriddenKeys.push(prop);
152
164
  }
153
- newEntries.push([prop, value]);
165
+ if (!isNewlyAdded &&
166
+ EventSpecContstants_1.MODIFY_EVENT_WHITELIST_STRING_FIELDS.includes(prop)) {
167
+ const maximumLength = Math.max(originalJSONEvent[prop].toString().length, EventSpecContstants_1.MAX_CUSTOM_EVENT_VALUE_LENGTH);
168
+ validEntries.push([
169
+ prop,
170
+ (0, EventModifierUtil_1.trimString)(prop, value.toString(), maximumLength),
171
+ ]);
172
+ }
173
+ else {
174
+ validEntries.push([prop, value]);
175
+ }
176
+ }
177
+ if (droppedCustomProperties) {
178
+ validEntries.push([
179
+ "dt.support.api.has_dropped_custom_properties",
180
+ true,
181
+ ]);
154
182
  }
155
- return newEntries;
183
+ if (droppedProperties) {
184
+ validEntries.push([
185
+ "dt.support.api.has_dropped_properties",
186
+ true,
187
+ ]);
188
+ }
189
+ return validEntries;
156
190
  }
157
191
  isModified(oldValue, newValue) {
158
192
  if (Array.isArray(oldValue)) {
@@ -198,5 +232,63 @@ class ModifyEventValidation {
198
232
  return entries;
199
233
  }, resultEntries);
200
234
  }
235
+ validateAddedEntries(addedEntries) {
236
+ const validEntries = [];
237
+ let droppedProperties = false;
238
+ let droppedCustomProperties = false;
239
+ for (const entry of addedEntries) {
240
+ if (!(0, EventModifierUtil_1.isNotObject)(entry) ||
241
+ !(0, EventModifierUtil_1.doesNotExceedKeySize)(entry) ||
242
+ !(0, EventModifierUtil_1.isKeySyntaxAllowed)(entry)) {
243
+ if ((0, EventModifierUtil_1.isKeyCustomProperty)(entry[0])) {
244
+ droppedCustomProperties = true;
245
+ }
246
+ else {
247
+ droppedProperties = true;
248
+ }
249
+ continue;
250
+ }
251
+ (0, EventModifierUtil_1.restrictingValueSize)(entry);
252
+ validEntries.push(entry);
253
+ }
254
+ if (droppedCustomProperties) {
255
+ validEntries.push([
256
+ "dt.support.api.has_dropped_custom_properties",
257
+ true,
258
+ ]);
259
+ }
260
+ if (droppedProperties) {
261
+ validEntries.push([
262
+ "dt.support.api.has_dropped_properties",
263
+ true,
264
+ ]);
265
+ }
266
+ return validEntries;
267
+ }
268
+ enforcePropertyLimit(entries) {
269
+ const result = [];
270
+ let propertyCount = 0;
271
+ let droppedCustomProperties = false;
272
+ entries.sort((a, b) => a[0].localeCompare(b[0]));
273
+ for (const [key, value] of entries) {
274
+ if ((0, EventModifierUtil_1.isKeyCustomProperty)(key)) {
275
+ propertyCount++;
276
+ if (propertyCount > EventSpecContstants_1.MAX_CUSTOM_EVENT_FIELDS) {
277
+ this.logger.debug(`enforcePropertyLimit(): Dropped ${key} because overall ` +
278
+ `property limit (${EventSpecContstants_1.MAX_CUSTOM_EVENT_FIELDS}) is reached!`);
279
+ droppedCustomProperties = true;
280
+ continue;
281
+ }
282
+ }
283
+ result.push([key, value]);
284
+ }
285
+ if (droppedCustomProperties) {
286
+ result.push([
287
+ "dt.support.api.has_dropped_custom_properties",
288
+ true,
289
+ ]);
290
+ }
291
+ return result;
292
+ }
201
293
  }
202
294
  exports.ModifyEventValidation = ModifyEventValidation;