avo-inspector 3.2.0 → 3.2.3

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 (84) hide show
  1. package/README.md +10 -0
  2. package/dist/AvoBatcher.d.ts +9 -3
  3. package/dist/AvoInspector.d.ts +4 -0
  4. package/dist/AvoNetworkCallsHandler.d.ts +80 -5
  5. package/dist/__tests__/UnboundPublicMethods_test.d.ts +1 -0
  6. package/dist/__tests__/constants.d.ts +2 -1
  7. package/dist/__tests__/helpers/internalGateway.d.ts +23 -0
  8. package/dist/eventSpec/AvoEventSpecCache.d.ts +7 -4
  9. package/dist/eventSpec/AvoEventSpecFetchTypes.d.ts +12 -1
  10. package/dist/eventSpec/AvoEventSpecFetcher.d.ts +6 -1
  11. package/dist/index.js +1 -1
  12. package/dist/lite/AvoBatcherLite.d.ts +9 -3
  13. package/dist/lite/AvoBatcherLite.js +46 -7
  14. package/dist/lite/AvoInspectorLite.d.ts +2 -0
  15. package/dist/lite/AvoInspectorLite.js +95 -15
  16. package/dist/lite/AvoNetworkCallsHandlerLite.d.ts +79 -5
  17. package/dist/lite/AvoNetworkCallsHandlerLite.js +300 -20
  18. package/package.json +10 -1
  19. package/dist/AvoBatcher.js +0 -87
  20. package/dist/AvoDeduplicator.js +0 -142
  21. package/dist/AvoEncryption.js +0 -176
  22. package/dist/AvoInspector.js +0 -435
  23. package/dist/AvoNetworkCallsHandler.js +0 -229
  24. package/dist/AvoSchemaParser.js +0 -95
  25. package/dist/AvoStreamId.js +0 -82
  26. package/dist/__mocks__/xhr.js +0 -14
  27. package/dist/__mocks__/xhrError.js +0 -14
  28. package/dist/__tests__/AvoEncryption.js +0 -272
  29. package/dist/__tests__/AvoEncryptionIntegration.js +0 -191
  30. package/dist/__tests__/AvoEventSpecFetcher.js +0 -377
  31. package/dist/__tests__/AvoInspector.js +0 -335
  32. package/dist/__tests__/Batcher.js +0 -214
  33. package/dist/__tests__/BatcherPublic.js +0 -139
  34. package/dist/__tests__/Deduplicator.js +0 -190
  35. package/dist/__tests__/EventSpecCache.js +0 -143
  36. package/dist/__tests__/EventValidator.js +0 -543
  37. package/dist/__tests__/InstallationId.js +0 -60
  38. package/dist/__tests__/NetworkCallsHandler.js +0 -222
  39. package/dist/__tests__/NetworkCallsHandlerModelA.js +0 -206
  40. package/dist/__tests__/Parsing.js +0 -115
  41. package/dist/__tests__/Sessions.d.ts +0 -1
  42. package/dist/__tests__/Sessions.js +0 -10
  43. package/dist/__tests__/Storage.d.ts +0 -1
  44. package/dist/__tests__/Storage.js +0 -173
  45. package/dist/__tests__/StreamId.d.ts +0 -1
  46. package/dist/__tests__/StreamId.js +0 -153
  47. package/dist/__tests__/constants.js +0 -48
  48. package/dist/esm/AvoBatcher.js +0 -75
  49. package/dist/esm/AvoDeduplicator.js +0 -137
  50. package/dist/esm/AvoEncryption.js +0 -277
  51. package/dist/esm/AvoGuid.js +0 -9
  52. package/dist/esm/AvoInspector.js +0 -470
  53. package/dist/esm/AvoInspectorEnv.js +0 -5
  54. package/dist/esm/AvoNetworkCallsHandler.js +0 -181
  55. package/dist/esm/AvoSchemaParser.js +0 -128
  56. package/dist/esm/AvoStorage.js +0 -176
  57. package/dist/esm/AvoStreamId.js +0 -140
  58. package/dist/esm/eventSpec/AvoEventSpecCache.js +0 -165
  59. package/dist/esm/eventSpec/AvoEventSpecFetchTypes.js +0 -6
  60. package/dist/esm/eventSpec/AvoEventSpecFetcher.js +0 -203
  61. package/dist/esm/eventSpec/EventValidator.js +0 -687
  62. package/dist/esm/eventSpec/index.js +0 -4
  63. package/dist/esm/index.js +0 -3
  64. package/dist/esm/utils.js +0 -38
  65. package/dist/esm/version.js +0 -2
  66. package/dist/eventSpec/AvoEventSpecCache.js +0 -181
  67. package/dist/eventSpec/AvoEventSpecFetcher.js +0 -290
  68. package/dist/eventSpec/EventValidator.js +0 -846
  69. package/dist/eventSpec/index.js +0 -20
  70. package/dist/version.d.ts +0 -1
  71. package/dist/version.js +0 -5
  72. /package/dist/__tests__/{AvoEncryption.d.ts → ApiKeyHeaderInjection_test.d.ts} +0 -0
  73. /package/dist/__tests__/{AvoEncryptionIntegration.d.ts → BrowserBootstrap_test.d.ts} +0 -0
  74. /package/dist/__tests__/{AvoEventSpecFetcher.d.ts → EventSpecGatewayCoordinates_test.d.ts} +0 -0
  75. /package/dist/__tests__/{AvoInspector.d.ts → InFlightQueueGaps_test.d.ts} +0 -0
  76. /package/dist/__tests__/{Batcher.d.ts → InFlightQueue_test.d.ts} +0 -0
  77. /package/dist/__tests__/{BatcherPublic.d.ts → NetworkCallsHandlerLite_test.d.ts} +0 -0
  78. /package/dist/__tests__/{Deduplicator.d.ts → PublicSurface_test.d.ts} +0 -0
  79. /package/dist/__tests__/{EventSpecCache.d.ts → TrackOptionsIntegration_test.d.ts} +0 -0
  80. /package/dist/__tests__/{EventValidator.d.ts → TrackOptionsTransport_test.d.ts} +0 -0
  81. /package/dist/__tests__/{InstallationId.d.ts → TrackingHeaders_test.d.ts} +0 -0
  82. /package/dist/__tests__/{NetworkCallsHandler.d.ts → V1WireBaseline_test.d.ts} +0 -0
  83. /package/dist/__tests__/{NetworkCallsHandlerModelA.d.ts → V2QueuedAttribution_test.d.ts} +0 -0
  84. /package/dist/__tests__/{Parsing.d.ts → V2StopSending_test.d.ts} +0 -0
@@ -1,846 +0,0 @@
1
- "use strict";
2
- /**
3
- * EventValidator - Client-side validation of tracking events against the Avo Tracking Plan.
4
- *
5
- * This module validates property values against constraints:
6
- * - Pinned values (exact match required)
7
- * - Allowed values (must be in list)
8
- * - Regex patterns (must match pattern, with safe-regex2 check and 1s timeout)
9
- * - Min/max ranges (numeric values must be in range)
10
- *
11
- * No schema validation (types/required) is performed - only value constraints.
12
- * Validation runs against ALL events/variants in the response.
13
- *
14
- * Adapted for React Native: uses safe-regex2 for regex safety and
15
- * Promise.race + clearTimeout for per-match 1-second timeout.
16
- */
17
- var __assign = (this && this.__assign) || function () {
18
- __assign = Object.assign || function(t) {
19
- for (var s, i = 1, n = arguments.length; i < n; i++) {
20
- s = arguments[i];
21
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
22
- t[p] = s[p];
23
- }
24
- return t;
25
- };
26
- return __assign.apply(this, arguments);
27
- };
28
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
29
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
30
- return new (P || (P = Promise))(function (resolve, reject) {
31
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
32
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
33
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
34
- step((generator = generator.apply(thisArg, _arguments || [])).next());
35
- });
36
- };
37
- var __generator = (this && this.__generator) || function (thisArg, body) {
38
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
39
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
40
- function verb(n) { return function (v) { return step([n, v]); }; }
41
- function step(op) {
42
- if (f) throw new TypeError("Generator is already executing.");
43
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
44
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
45
- if (y = 0, t) op = [op[0] & 2, t.value];
46
- switch (op[0]) {
47
- case 0: case 1: t = op; break;
48
- case 4: _.label++; return { value: op[1], done: false };
49
- case 5: _.label++; y = op[1]; op = [0]; continue;
50
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
51
- default:
52
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
53
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
54
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
55
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
56
- if (t[2]) _.ops.pop();
57
- _.trys.pop(); continue;
58
- }
59
- op = body.call(thisArg, _);
60
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
61
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
62
- }
63
- };
64
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
65
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
66
- if (ar || !(i in from)) {
67
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
68
- ar[i] = from[i];
69
- }
70
- }
71
- return to.concat(ar || Array.prototype.slice.call(from));
72
- };
73
- Object.defineProperty(exports, "__esModule", { value: true });
74
- exports.validateEvent = validateEvent;
75
- var safe = require("safe-regex2");
76
- // =============================================================================
77
- // HELPER FUNCTIONS FOR NESTED PROPERTIES
78
- // =============================================================================
79
- /**
80
- * Deep copies a constraint mapping (pinnedValues, allowedValues, etc.),
81
- * including the arrays inside to avoid shared references.
82
- */
83
- function deepCopyConstraintMapping(mapping) {
84
- var result = {};
85
- for (var _i = 0, _a = Object.entries(mapping); _i < _a.length; _i++) {
86
- var _b = _a[_i], key = _b[0], arr = _b[1];
87
- result[key] = __spreadArray([], arr, true);
88
- }
89
- return result;
90
- }
91
- /**
92
- * Deep copies children constraints recursively.
93
- */
94
- function deepCopyChildren(children) {
95
- var result = {};
96
- for (var _i = 0, _a = Object.entries(children); _i < _a.length; _i++) {
97
- var _b = _a[_i], propName = _b[0], constraints = _b[1];
98
- result[propName] = {
99
- type: constraints.type,
100
- required: constraints.required,
101
- pinnedValues: constraints.pinnedValues
102
- ? deepCopyConstraintMapping(constraints.pinnedValues)
103
- : undefined,
104
- allowedValues: constraints.allowedValues
105
- ? deepCopyConstraintMapping(constraints.allowedValues)
106
- : undefined,
107
- regexPatterns: constraints.regexPatterns
108
- ? deepCopyConstraintMapping(constraints.regexPatterns)
109
- : undefined,
110
- minMaxRanges: constraints.minMaxRanges
111
- ? deepCopyConstraintMapping(constraints.minMaxRanges)
112
- : undefined,
113
- children: constraints.children
114
- ? deepCopyChildren(constraints.children)
115
- : undefined
116
- };
117
- }
118
- return result;
119
- }
120
- /**
121
- * Merges children constraints from source into target recursively.
122
- */
123
- function mergeChildren(target, source) {
124
- for (var _i = 0, _a = Object.entries(source); _i < _a.length; _i++) {
125
- var _b = _a[_i], propName = _b[0], sourceConstraints = _b[1];
126
- if (!target[propName]) {
127
- // New child property - deep copy it
128
- target[propName] = {
129
- type: sourceConstraints.type,
130
- required: sourceConstraints.required,
131
- pinnedValues: sourceConstraints.pinnedValues
132
- ? deepCopyConstraintMapping(sourceConstraints.pinnedValues)
133
- : undefined,
134
- allowedValues: sourceConstraints.allowedValues
135
- ? deepCopyConstraintMapping(sourceConstraints.allowedValues)
136
- : undefined,
137
- regexPatterns: sourceConstraints.regexPatterns
138
- ? deepCopyConstraintMapping(sourceConstraints.regexPatterns)
139
- : undefined,
140
- minMaxRanges: sourceConstraints.minMaxRanges
141
- ? deepCopyConstraintMapping(sourceConstraints.minMaxRanges)
142
- : undefined,
143
- children: sourceConstraints.children
144
- ? deepCopyChildren(sourceConstraints.children)
145
- : undefined
146
- };
147
- }
148
- else {
149
- // Merge into existing child property
150
- var targetConstraints = target[propName];
151
- mergeConstraintMappings(targetConstraints, sourceConstraints);
152
- // Recursively merge nested children
153
- if (sourceConstraints.children) {
154
- if (!targetConstraints.children) {
155
- targetConstraints.children = deepCopyChildren(sourceConstraints.children);
156
- }
157
- else {
158
- mergeChildren(targetConstraints.children, sourceConstraints.children);
159
- }
160
- }
161
- }
162
- }
163
- }
164
- /**
165
- * Merges constraint mappings (pinnedValues, allowedValues, etc.) from source into target.
166
- */
167
- function mergeConstraintMappings(target, source) {
168
- if (source.pinnedValues) {
169
- if (!target.pinnedValues) {
170
- target.pinnedValues = {};
171
- }
172
- for (var _i = 0, _a = Object.keys(source.pinnedValues); _i < _a.length; _i++) {
173
- var key = _a[_i];
174
- if (target.pinnedValues[key]) {
175
- var merged = new Set(target.pinnedValues[key]);
176
- for (var _b = 0, _c = source.pinnedValues[key]; _b < _c.length; _b++) {
177
- var id = _c[_b];
178
- merged.add(id);
179
- }
180
- target.pinnedValues[key] = Array.from(merged);
181
- }
182
- else {
183
- target.pinnedValues[key] = __spreadArray([], source.pinnedValues[key], true);
184
- }
185
- }
186
- }
187
- if (source.allowedValues) {
188
- if (!target.allowedValues) {
189
- target.allowedValues = {};
190
- }
191
- for (var _d = 0, _e = Object.keys(source.allowedValues); _d < _e.length; _d++) {
192
- var key = _e[_d];
193
- if (target.allowedValues[key]) {
194
- var merged = new Set(target.allowedValues[key]);
195
- for (var _f = 0, _g = source.allowedValues[key]; _f < _g.length; _f++) {
196
- var id = _g[_f];
197
- merged.add(id);
198
- }
199
- target.allowedValues[key] = Array.from(merged);
200
- }
201
- else {
202
- target.allowedValues[key] = __spreadArray([], source.allowedValues[key], true);
203
- }
204
- }
205
- }
206
- if (source.regexPatterns) {
207
- if (!target.regexPatterns) {
208
- target.regexPatterns = {};
209
- }
210
- for (var _h = 0, _j = Object.keys(source.regexPatterns); _h < _j.length; _h++) {
211
- var key = _j[_h];
212
- if (target.regexPatterns[key]) {
213
- var merged = new Set(target.regexPatterns[key]);
214
- for (var _k = 0, _l = source.regexPatterns[key]; _k < _l.length; _k++) {
215
- var id = _l[_k];
216
- merged.add(id);
217
- }
218
- target.regexPatterns[key] = Array.from(merged);
219
- }
220
- else {
221
- target.regexPatterns[key] = __spreadArray([], source.regexPatterns[key], true);
222
- }
223
- }
224
- }
225
- if (source.minMaxRanges) {
226
- if (!target.minMaxRanges) {
227
- target.minMaxRanges = {};
228
- }
229
- for (var _m = 0, _o = Object.keys(source.minMaxRanges); _m < _o.length; _m++) {
230
- var key = _o[_m];
231
- if (target.minMaxRanges[key]) {
232
- var merged = new Set(target.minMaxRanges[key]);
233
- for (var _p = 0, _q = source.minMaxRanges[key]; _p < _q.length; _p++) {
234
- var id = _q[_p];
235
- merged.add(id);
236
- }
237
- target.minMaxRanges[key] = Array.from(merged);
238
- }
239
- else {
240
- target.minMaxRanges[key] = __spreadArray([], source.minMaxRanges[key], true);
241
- }
242
- }
243
- }
244
- }
245
- // =============================================================================
246
- // CACHES
247
- // =============================================================================
248
- /**
249
- * Cache for compiled regex objects to avoid recompilation on every event.
250
- * Patterns are expected to be stable per session.
251
- * Only safe patterns (per safe-regex2) are cached.
252
- */
253
- var regexCache = new Map();
254
- /**
255
- * Gets a compiled regex from cache or compiles and caches it.
256
- * Uses safe-regex2 to validate patterns before compilation.
257
- * Returns null if the pattern is unsafe or invalid.
258
- */
259
- function getOrCompileRegex(pattern) {
260
- var regex = regexCache.get(pattern);
261
- if (regex) {
262
- return regex;
263
- }
264
- // Check pattern safety with safe-regex2
265
- if (!safe(pattern)) {
266
- console.warn("[Avo Inspector] Warning: unsafe regex pattern skipped: ".concat(pattern));
267
- return null;
268
- }
269
- try {
270
- regex = new RegExp(pattern);
271
- regexCache.set(pattern, regex);
272
- return regex;
273
- }
274
- catch (e) {
275
- console.warn("[Avo Inspector] Warning: invalid regex pattern skipped: ".concat(pattern));
276
- return null;
277
- }
278
- }
279
- /**
280
- * Tests a regex match with a 1-second timeout using Promise.race + clearTimeout.
281
- * The timer is cleared on regex completion to prevent timer accumulation.
282
- * Returns true if pattern matches, false if not or on timeout.
283
- *
284
- * Note: safe-regex2 is the primary ReDoS protection — it screens out catastrophic
285
- * patterns before they are compiled. This timeout is a safety net for future async
286
- * regex engines or edge cases where safe-regex2 does not catch the pattern.
287
- */
288
- function testRegexWithTimeout(regex_1, value_1) {
289
- return __awaiter(this, arguments, void 0, function (regex, value, timeoutMs) {
290
- if (timeoutMs === void 0) { timeoutMs = 1000; }
291
- return __generator(this, function (_a) {
292
- return [2 /*return*/, new Promise(function (resolve) {
293
- var settled = false;
294
- var timer = setTimeout(function () {
295
- if (!settled) {
296
- settled = true;
297
- console.warn("[Avo Inspector] Warning: regex match timed out after ".concat(timeoutMs, "ms"));
298
- resolve(false);
299
- }
300
- }, timeoutMs);
301
- try {
302
- var result = regex.test(value);
303
- if (!settled) {
304
- settled = true;
305
- clearTimeout(timer);
306
- resolve(result);
307
- }
308
- }
309
- catch (e) {
310
- if (!settled) {
311
- settled = true;
312
- clearTimeout(timer);
313
- resolve(false);
314
- }
315
- }
316
- })];
317
- });
318
- });
319
- }
320
- /**
321
- * Cache for parsed allowed values JSON.
322
- * Key: JSON string, Value: Set of allowed values for O(1) lookup.
323
- */
324
- var allowedValuesCache = new Map();
325
- /**
326
- * Parses allowed values JSON string and returns a Set for O(1) lookup.
327
- * Results are cached to avoid repeated JSON.parse calls.
328
- * @returns Set of allowed values, or null if JSON is invalid
329
- */
330
- function getOrParseAllowedValues(jsonString) {
331
- var allowedSet = allowedValuesCache.get(jsonString);
332
- if (!allowedSet) {
333
- try {
334
- var allowedArray = JSON.parse(jsonString);
335
- allowedSet = new Set(allowedArray);
336
- allowedValuesCache.set(jsonString, allowedSet);
337
- }
338
- catch (e) {
339
- // Invalid JSON - return null
340
- return null;
341
- }
342
- }
343
- return allowedSet;
344
- }
345
- // =============================================================================
346
- // MAIN VALIDATION FUNCTION
347
- // =============================================================================
348
- /**
349
- * Validates runtime properties against all events in the EventSpecResponse.
350
- *
351
- * For each property:
352
- * - If property not in spec: no validation needed (empty result)
353
- * - If property in spec: check constraints and collect failed/passed eventIds
354
- * - Return whichever list is smaller for bandwidth optimization
355
- *
356
- * This is an async function because regex validation uses Promise.race for timeout.
357
- *
358
- * @param properties - The properties observed at runtime
359
- * @param specResponse - The EventSpecResponse from the backend
360
- * @returns ValidationResult with metadata and per-property results
361
- */
362
- function validateEvent(properties, specResponse) {
363
- return __awaiter(this, void 0, void 0, function () {
364
- var allEventIds, constraintsByProperty, propertyResults, _i, _a, propName, value, constraints, result;
365
- return __generator(this, function (_b) {
366
- switch (_b.label) {
367
- case 0:
368
- allEventIds = collectAllEventIds(specResponse.events);
369
- constraintsByProperty = collectConstraintsByPropertyName(specResponse.events);
370
- propertyResults = {};
371
- _i = 0, _a = Object.keys(properties);
372
- _b.label = 1;
373
- case 1:
374
- if (!(_i < _a.length)) return [3 /*break*/, 5];
375
- propName = _a[_i];
376
- value = properties[propName];
377
- constraints = constraintsByProperty[propName];
378
- if (!!constraints) return [3 /*break*/, 2];
379
- // Property not in spec - no constraints to fail
380
- propertyResults[propName] = {};
381
- return [3 /*break*/, 4];
382
- case 2: return [4 /*yield*/, validatePropertyConstraints(value, constraints, allEventIds)];
383
- case 3:
384
- result = _b.sent();
385
- propertyResults[propName] = result;
386
- _b.label = 4;
387
- case 4:
388
- _i++;
389
- return [3 /*break*/, 1];
390
- case 5: return [2 /*return*/, {
391
- metadata: specResponse.metadata,
392
- propertyResults: propertyResults
393
- }];
394
- }
395
- });
396
- });
397
- }
398
- // =============================================================================
399
- // HELPER FUNCTIONS
400
- // =============================================================================
401
- /**
402
- * Collects all eventIds (baseEventId + variantIds) from all events.
403
- */
404
- function collectAllEventIds(events) {
405
- var ids = [];
406
- for (var _i = 0, events_1 = events; _i < events_1.length; _i++) {
407
- var event_1 = events_1[_i];
408
- ids.push(event_1.baseEventId);
409
- for (var j = 0; j < event_1.variantIds.length; j++) {
410
- ids.push(event_1.variantIds[j]);
411
- }
412
- }
413
- return ids;
414
- }
415
- /**
416
- * Collects all property constraints from all events into a single lookup table.
417
- */
418
- function collectConstraintsByPropertyName(events) {
419
- // Fast path: no events
420
- if (events.length === 0) {
421
- return {};
422
- }
423
- // Fast path: single event, return props directly (no aggregation needed)
424
- if (events.length === 1) {
425
- return events[0].props;
426
- }
427
- // Multiple events: aggregate constraints from all events
428
- var result = {};
429
- for (var _i = 0, events_2 = events; _i < events_2.length; _i++) {
430
- var event_2 = events_2[_i];
431
- for (var _a = 0, _b = Object.entries(event_2.props); _a < _b.length; _a++) {
432
- var _c = _b[_a], propName = _c[0], constraints = _c[1];
433
- if (!result[propName]) {
434
- // First time seeing this property - initialize with copies
435
- result[propName] = {
436
- type: constraints.type,
437
- required: constraints.required,
438
- pinnedValues: constraints.pinnedValues
439
- ? __assign({}, constraints.pinnedValues) : undefined,
440
- allowedValues: constraints.allowedValues
441
- ? __assign({}, constraints.allowedValues) : undefined,
442
- regexPatterns: constraints.regexPatterns
443
- ? __assign({}, constraints.regexPatterns) : undefined,
444
- minMaxRanges: constraints.minMaxRanges
445
- ? __assign({}, constraints.minMaxRanges) : undefined,
446
- children: constraints.children
447
- ? deepCopyChildren(constraints.children)
448
- : undefined
449
- };
450
- }
451
- else {
452
- // Aggregate constraint mappings from additional events
453
- var existing = result[propName];
454
- mergeConstraintMappings(existing, constraints);
455
- // Recursively merge nested children
456
- if (constraints.children) {
457
- if (!existing.children) {
458
- existing.children = deepCopyChildren(constraints.children);
459
- }
460
- else {
461
- mergeChildren(existing.children, constraints.children);
462
- }
463
- }
464
- }
465
- }
466
- }
467
- return result;
468
- }
469
- /**
470
- * Maximum nesting depth for recursive value validation.
471
- */
472
- var MAX_CHILD_DEPTH = 2;
473
- /**
474
- * Validates a property value against its constraints.
475
- */
476
- function validatePropertyConstraints(value_1, constraints_1, allEventIds_1) {
477
- return __awaiter(this, arguments, void 0, function (value, constraints, allEventIds, depth) {
478
- var result;
479
- if (depth === void 0) { depth = 0; }
480
- return __generator(this, function (_a) {
481
- result = {};
482
- if (depth >= MAX_CHILD_DEPTH) {
483
- return [2 /*return*/, result];
484
- }
485
- // Handle list types (isList=true)
486
- if (constraints.isList) {
487
- return [2 /*return*/, validateListProperty(value, constraints, allEventIds, depth)];
488
- }
489
- // Handle nested object properties with children (single object, not list)
490
- if (constraints.children) {
491
- return [2 /*return*/, validateObjectProperty(value, constraints, allEventIds, depth)];
492
- }
493
- // For primitive properties only: skip validation for null/undefined on non-required properties.
494
- if ((value === null || value === undefined) && !constraints.required) {
495
- return [2 /*return*/, result];
496
- }
497
- // Validate value constraints for primitive properties
498
- return [2 /*return*/, validatePrimitiveProperty(value, constraints, allEventIds)];
499
- });
500
- });
501
- }
502
- /**
503
- * Validates a list property (array of items).
504
- */
505
- function validateListProperty(value, constraints, allEventIds, depth) {
506
- return __awaiter(this, void 0, void 0, function () {
507
- var result, childrenResults, _loop_1, _i, _a, _b, childName, childConstraints, failedIds, _c, value_1, item;
508
- return __generator(this, function (_d) {
509
- switch (_d.label) {
510
- case 0:
511
- result = {};
512
- if (!Array.isArray(value)) {
513
- return [2 /*return*/, result];
514
- }
515
- if (!constraints.children) return [3 /*break*/, 5];
516
- childrenResults = {};
517
- _loop_1 = function (childName, childConstraints) {
518
- var aggregatedFailedIds, _e, value_2, item, itemObj, childValue, childResult, _f, _g, id, passedSet, _h, allEventIds_1, id, failedArray, passedIds;
519
- return __generator(this, function (_j) {
520
- switch (_j.label) {
521
- case 0:
522
- aggregatedFailedIds = new Set();
523
- _e = 0, value_2 = value;
524
- _j.label = 1;
525
- case 1:
526
- if (!(_e < value_2.length)) return [3 /*break*/, 4];
527
- item = value_2[_e];
528
- itemObj = (typeof item === "object" && item !== null && !Array.isArray(item))
529
- ? item
530
- : {};
531
- childValue = itemObj[childName];
532
- return [4 /*yield*/, validatePropertyConstraints(childValue, childConstraints, allEventIds, depth + 1)];
533
- case 2:
534
- childResult = _j.sent();
535
- if (childResult.failedEventIds) {
536
- for (_f = 0, _g = childResult.failedEventIds; _f < _g.length; _f++) {
537
- id = _g[_f];
538
- aggregatedFailedIds.add(id);
539
- }
540
- }
541
- if (childResult.passedEventIds) {
542
- passedSet = new Set(childResult.passedEventIds);
543
- for (_h = 0, allEventIds_1 = allEventIds; _h < allEventIds_1.length; _h++) {
544
- id = allEventIds_1[_h];
545
- if (!passedSet.has(id)) {
546
- aggregatedFailedIds.add(id);
547
- }
548
- }
549
- }
550
- _j.label = 3;
551
- case 3:
552
- _e++;
553
- return [3 /*break*/, 1];
554
- case 4:
555
- if (aggregatedFailedIds.size > 0) {
556
- failedArray = Array.from(aggregatedFailedIds);
557
- passedIds = allEventIds.filter(function (id) { return !aggregatedFailedIds.has(id); });
558
- if (passedIds.length < failedArray.length && passedIds.length > 0) {
559
- childrenResults[childName] = { passedEventIds: passedIds };
560
- }
561
- else {
562
- childrenResults[childName] = { failedEventIds: failedArray };
563
- }
564
- }
565
- return [2 /*return*/];
566
- }
567
- });
568
- };
569
- _i = 0, _a = Object.entries(constraints.children);
570
- _d.label = 1;
571
- case 1:
572
- if (!(_i < _a.length)) return [3 /*break*/, 4];
573
- _b = _a[_i], childName = _b[0], childConstraints = _b[1];
574
- return [5 /*yield**/, _loop_1(childName, childConstraints)];
575
- case 2:
576
- _d.sent();
577
- _d.label = 3;
578
- case 3:
579
- _i++;
580
- return [3 /*break*/, 1];
581
- case 4:
582
- if (Object.keys(childrenResults).length > 0) {
583
- result.children = childrenResults;
584
- }
585
- return [2 /*return*/, result];
586
- case 5:
587
- failedIds = new Set();
588
- _c = 0, value_1 = value;
589
- _d.label = 6;
590
- case 6:
591
- if (!(_c < value_1.length)) return [3 /*break*/, 10];
592
- item = value_1[_c];
593
- if (constraints.pinnedValues) {
594
- checkPinnedValues(item, constraints.pinnedValues, failedIds);
595
- }
596
- if (constraints.allowedValues) {
597
- checkAllowedValues(item, constraints.allowedValues, failedIds);
598
- }
599
- if (!constraints.regexPatterns) return [3 /*break*/, 8];
600
- return [4 /*yield*/, checkRegexPatterns(item, constraints.regexPatterns, failedIds)];
601
- case 7:
602
- _d.sent();
603
- _d.label = 8;
604
- case 8:
605
- if (constraints.minMaxRanges) {
606
- checkMinMaxRanges(item, constraints.minMaxRanges, failedIds);
607
- }
608
- _d.label = 9;
609
- case 9:
610
- _c++;
611
- return [3 /*break*/, 6];
612
- case 10: return [2 /*return*/, buildValidationResult(failedIds, allEventIds)];
613
- }
614
- });
615
- });
616
- }
617
- /**
618
- * Validates an object property (single object with children).
619
- */
620
- function validateObjectProperty(value, constraints, allEventIds, depth) {
621
- return __awaiter(this, void 0, void 0, function () {
622
- var result, childrenResults, valueObj, _i, _a, _b, childName, childConstraints, childValue, childResult;
623
- return __generator(this, function (_c) {
624
- switch (_c.label) {
625
- case 0:
626
- result = {};
627
- childrenResults = {};
628
- valueObj = (typeof value === "object" && value !== null && !Array.isArray(value))
629
- ? value
630
- : {};
631
- _i = 0, _a = Object.entries(constraints.children);
632
- _c.label = 1;
633
- case 1:
634
- if (!(_i < _a.length)) return [3 /*break*/, 4];
635
- _b = _a[_i], childName = _b[0], childConstraints = _b[1];
636
- childValue = valueObj[childName];
637
- return [4 /*yield*/, validatePropertyConstraints(childValue, childConstraints, allEventIds, depth + 1)];
638
- case 2:
639
- childResult = _c.sent();
640
- if (childResult.failedEventIds || childResult.passedEventIds || childResult.children) {
641
- childrenResults[childName] = childResult;
642
- }
643
- _c.label = 3;
644
- case 3:
645
- _i++;
646
- return [3 /*break*/, 1];
647
- case 4:
648
- if (Object.keys(childrenResults).length > 0) {
649
- result.children = childrenResults;
650
- }
651
- return [2 /*return*/, result];
652
- }
653
- });
654
- });
655
- }
656
- /**
657
- * Validates a primitive property (not list, not object with children).
658
- */
659
- function validatePrimitiveProperty(value, constraints, allEventIds) {
660
- return __awaiter(this, void 0, void 0, function () {
661
- var failedIds;
662
- return __generator(this, function (_a) {
663
- switch (_a.label) {
664
- case 0:
665
- failedIds = new Set();
666
- if (constraints.pinnedValues) {
667
- checkPinnedValues(value, constraints.pinnedValues, failedIds);
668
- }
669
- if (constraints.allowedValues) {
670
- checkAllowedValues(value, constraints.allowedValues, failedIds);
671
- }
672
- if (!constraints.regexPatterns) return [3 /*break*/, 2];
673
- return [4 /*yield*/, checkRegexPatterns(value, constraints.regexPatterns, failedIds)];
674
- case 1:
675
- _a.sent();
676
- _a.label = 2;
677
- case 2:
678
- if (constraints.minMaxRanges) {
679
- checkMinMaxRanges(value, constraints.minMaxRanges, failedIds);
680
- }
681
- return [2 /*return*/, buildValidationResult(failedIds, allEventIds)];
682
- }
683
- });
684
- });
685
- }
686
- /**
687
- * Builds the validation result from failed IDs, returning whichever list is smaller.
688
- */
689
- function buildValidationResult(failedIds, allEventIds) {
690
- var passedIds = allEventIds.filter(function (id) { return !failedIds.has(id); });
691
- var failedArray = Array.from(failedIds);
692
- if (failedArray.length === 0 && passedIds.length === 0) {
693
- return {};
694
- }
695
- // Prefer passedEventIds only when strictly smaller than failedEventIds
696
- if (passedIds.length < failedArray.length && passedIds.length > 0) {
697
- return { passedEventIds: passedIds };
698
- }
699
- else if (failedArray.length > 0) {
700
- return { failedEventIds: failedArray };
701
- }
702
- else {
703
- return {};
704
- }
705
- }
706
- // =============================================================================
707
- // CONSTRAINT VALIDATION FUNCTIONS
708
- // =============================================================================
709
- /**
710
- * Adds all IDs from the array to the set.
711
- */
712
- function addIdsToSet(ids, set) {
713
- for (var _i = 0, ids_1 = ids; _i < ids_1.length; _i++) {
714
- var id = ids_1[_i];
715
- set.add(id);
716
- }
717
- }
718
- /**
719
- * Converts runtime value to string for comparison.
720
- */
721
- function convertValueToString(value) {
722
- if (value === null ||
723
- value === undefined ||
724
- typeof value === "boolean" ||
725
- typeof value === "number" ||
726
- typeof value === "string") {
727
- return String(value);
728
- }
729
- if (Array.isArray(value) || typeof value === "object") {
730
- try {
731
- return JSON.stringify(value);
732
- }
733
- catch (e) {
734
- console.warn("[Avo Inspector] Failed to stringify value: ".concat(e));
735
- return String(value);
736
- }
737
- }
738
- return String(value);
739
- }
740
- /**
741
- * Checks pinned values constraint.
742
- */
743
- function checkPinnedValues(value, pinnedValues, failedIds) {
744
- var stringValue = convertValueToString(value);
745
- for (var _i = 0, _a = Object.entries(pinnedValues); _i < _a.length; _i++) {
746
- var _b = _a[_i], pinnedValue = _b[0], eventIds = _b[1];
747
- if (stringValue !== pinnedValue) {
748
- addIdsToSet(eventIds, failedIds);
749
- }
750
- }
751
- }
752
- /**
753
- * Checks allowed values constraint.
754
- */
755
- function checkAllowedValues(value, allowedValues, failedIds) {
756
- var stringValue = convertValueToString(value);
757
- for (var _i = 0, _a = Object.entries(allowedValues); _i < _a.length; _i++) {
758
- var _b = _a[_i], allowedArrayJson = _b[0], eventIds = _b[1];
759
- var allowedSet = getOrParseAllowedValues(allowedArrayJson);
760
- if (allowedSet === null) {
761
- console.warn("[Avo Inspector] Invalid allowed values JSON: ".concat(allowedArrayJson));
762
- continue;
763
- }
764
- if (!allowedSet.has(stringValue)) {
765
- addIdsToSet(eventIds, failedIds);
766
- }
767
- }
768
- }
769
- /**
770
- * Checks regex pattern constraint with safe-regex2 validation and 1-second timeout.
771
- * Unsafe patterns are skipped with a console.warn.
772
- */
773
- function checkRegexPatterns(value, regexPatterns, failedIds) {
774
- return __awaiter(this, void 0, void 0, function () {
775
- var _i, _a, eventIds, _b, _c, _d, pattern, eventIds, regex, matched;
776
- return __generator(this, function (_e) {
777
- switch (_e.label) {
778
- case 0:
779
- // Only check regex for string values
780
- if (typeof value !== "string") {
781
- for (_i = 0, _a = Object.values(regexPatterns); _i < _a.length; _i++) {
782
- eventIds = _a[_i];
783
- addIdsToSet(eventIds, failedIds);
784
- }
785
- return [2 /*return*/];
786
- }
787
- _b = 0, _c = Object.entries(regexPatterns);
788
- _e.label = 1;
789
- case 1:
790
- if (!(_b < _c.length)) return [3 /*break*/, 4];
791
- _d = _c[_b], pattern = _d[0], eventIds = _d[1];
792
- regex = getOrCompileRegex(pattern);
793
- if (regex === null) {
794
- // Pattern was unsafe or invalid - skip (warning already logged)
795
- return [3 /*break*/, 3];
796
- }
797
- return [4 /*yield*/, testRegexWithTimeout(regex, value, 1000)];
798
- case 2:
799
- matched = _e.sent();
800
- if (!matched) {
801
- addIdsToSet(eventIds, failedIds);
802
- }
803
- _e.label = 3;
804
- case 3:
805
- _b++;
806
- return [3 /*break*/, 1];
807
- case 4: return [2 /*return*/];
808
- }
809
- });
810
- });
811
- }
812
- /**
813
- * Checks min/max range constraint.
814
- */
815
- function checkMinMaxRanges(value, minMaxRanges, failedIds) {
816
- if (typeof value !== "number") {
817
- for (var _i = 0, _a = Object.values(minMaxRanges); _i < _a.length; _i++) {
818
- var eventIds = _a[_i];
819
- addIdsToSet(eventIds, failedIds);
820
- }
821
- return;
822
- }
823
- if (Number.isNaN(value)) {
824
- console.warn("[Avo Inspector] NaN value fails min/max constraint");
825
- for (var _b = 0, _c = Object.values(minMaxRanges); _b < _c.length; _b++) {
826
- var eventIds = _c[_b];
827
- addIdsToSet(eventIds, failedIds);
828
- }
829
- return;
830
- }
831
- for (var _d = 0, _e = Object.entries(minMaxRanges); _d < _e.length; _d++) {
832
- var _f = _e[_d], rangeStr = _f[0], eventIds = _f[1];
833
- var _g = rangeStr.split(","), minStr = _g[0], maxStr = _g[1];
834
- var hasMin = minStr !== "" && minStr !== undefined;
835
- var hasMax = maxStr !== "" && maxStr !== undefined;
836
- var min = hasMin ? parseFloat(minStr) : -Infinity;
837
- var max = hasMax ? parseFloat(maxStr) : Infinity;
838
- if ((hasMin && isNaN(min)) || (hasMax && isNaN(max))) {
839
- console.warn("[Avo Inspector] Invalid min/max range: ".concat(rangeStr));
840
- continue;
841
- }
842
- if (value < min || value > max) {
843
- addIdsToSet(eventIds, failedIds);
844
- }
845
- }
846
- }