avo-inspector 3.1.0-alpha.2 → 3.2.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 (52) hide show
  1. package/README.md +6 -13
  2. package/dist/AvoBatcher.js +52 -44
  3. package/dist/AvoDeduplicator.js +46 -45
  4. package/dist/AvoEncryption.js +147 -253
  5. package/dist/AvoInspector.js +295 -334
  6. package/dist/AvoNetworkCallsHandler.d.ts +6 -0
  7. package/dist/AvoNetworkCallsHandler.js +180 -136
  8. package/dist/AvoSchemaParser.js +34 -71
  9. package/dist/AvoStreamId.js +67 -129
  10. package/dist/__mocks__/xhr.js +14 -0
  11. package/dist/__mocks__/xhrError.js +14 -0
  12. package/dist/__tests__/AvoEncryption.d.ts +1 -0
  13. package/dist/__tests__/AvoEncryption.js +272 -0
  14. package/dist/__tests__/AvoEncryptionIntegration.d.ts +1 -0
  15. package/dist/__tests__/AvoEncryptionIntegration.js +191 -0
  16. package/dist/__tests__/AvoEventSpecFetcher.d.ts +1 -0
  17. package/dist/__tests__/AvoEventSpecFetcher.js +377 -0
  18. package/dist/__tests__/AvoInspector.d.ts +1 -0
  19. package/dist/__tests__/AvoInspector.js +335 -0
  20. package/dist/__tests__/Batcher.d.ts +1 -0
  21. package/dist/__tests__/Batcher.js +214 -0
  22. package/dist/__tests__/BatcherPublic.d.ts +1 -0
  23. package/dist/__tests__/BatcherPublic.js +139 -0
  24. package/dist/__tests__/Deduplicator.d.ts +1 -0
  25. package/dist/__tests__/Deduplicator.js +190 -0
  26. package/dist/__tests__/EventSpecCache.d.ts +1 -0
  27. package/dist/__tests__/EventSpecCache.js +143 -0
  28. package/dist/__tests__/EventValidator.d.ts +1 -0
  29. package/dist/__tests__/EventValidator.js +543 -0
  30. package/dist/__tests__/InstallationId.d.ts +1 -0
  31. package/dist/__tests__/InstallationId.js +60 -0
  32. package/dist/__tests__/NetworkCallsHandler.d.ts +1 -0
  33. package/dist/__tests__/NetworkCallsHandler.js +222 -0
  34. package/dist/__tests__/NetworkCallsHandlerGzip_test.d.ts +1 -0
  35. package/dist/__tests__/NetworkCallsHandlerModelA.d.ts +1 -0
  36. package/dist/__tests__/NetworkCallsHandlerModelA.js +206 -0
  37. package/dist/__tests__/Parsing.d.ts +1 -0
  38. package/dist/__tests__/Parsing.js +115 -0
  39. package/dist/__tests__/Sessions.d.ts +1 -0
  40. package/dist/__tests__/Sessions.js +10 -0
  41. package/dist/__tests__/Storage.d.ts +1 -0
  42. package/dist/__tests__/Storage.js +173 -0
  43. package/dist/__tests__/StreamId.d.ts +1 -0
  44. package/dist/__tests__/StreamId.js +153 -0
  45. package/dist/__tests__/constants.js +48 -0
  46. package/dist/eventSpec/AvoEventSpecCache.js +94 -82
  47. package/dist/eventSpec/AvoEventSpecFetcher.js +200 -117
  48. package/dist/eventSpec/EventValidator.js +460 -304
  49. package/dist/index.js +1 -1
  50. package/dist/lite/AvoNetworkCallsHandlerLite.d.ts +6 -0
  51. package/dist/lite/AvoNetworkCallsHandlerLite.js +110 -1
  52. package/package.json +2 -2
@@ -1,51 +1,64 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ 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;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
2
38
  Object.defineProperty(exports, "__esModule", { value: true });
3
39
  exports.AvoInspector = void 0;
4
- const AvoInspectorEnv_1 = require("./AvoInspectorEnv");
5
- const AvoSchemaParser_1 = require("./AvoSchemaParser");
6
- const AvoBatcher_1 = require("./AvoBatcher");
7
- const AvoNetworkCallsHandler_1 = require("./AvoNetworkCallsHandler");
8
- const AvoStorage_1 = require("./AvoStorage");
9
- const AvoDeduplicator_1 = require("./AvoDeduplicator");
10
- const AvoStreamId_1 = require("./AvoStreamId");
11
- const utils_1 = require("./utils");
12
- const version_1 = require("./version");
13
- const libVersion = version_1.LIB_VERSION;
14
- class AvoInspector {
15
- static get batchSize() {
16
- return this._batchSize;
17
- }
18
- static set batchSize(newSize) {
19
- if (newSize < 1) {
20
- this._batchSize = 1;
21
- }
22
- else {
23
- this._batchSize = newSize;
24
- }
25
- }
26
- static get batchFlushSeconds() {
27
- return this._batchFlushSeconds;
28
- }
29
- static get shouldLog() {
30
- return this._shouldLog;
31
- }
32
- static set shouldLog(enable) {
33
- this._shouldLog = enable;
34
- }
35
- static get networkTimeout() {
36
- return this._networkTimeout;
37
- }
38
- static set networkTimeout(timeout) {
39
- this._networkTimeout = timeout;
40
- }
41
- constructor(options) {
40
+ var AvoInspectorEnv_1 = require("./AvoInspectorEnv");
41
+ var AvoSchemaParser_1 = require("./AvoSchemaParser");
42
+ var AvoBatcher_1 = require("./AvoBatcher");
43
+ var AvoNetworkCallsHandler_1 = require("./AvoNetworkCallsHandler");
44
+ var AvoStorage_1 = require("./AvoStorage");
45
+ var AvoDeduplicator_1 = require("./AvoDeduplicator");
46
+ var AvoStreamId_1 = require("./AvoStreamId");
47
+ var AvoEventSpecCache_1 = require("./eventSpec/AvoEventSpecCache");
48
+ var AvoEventSpecFetcher_1 = require("./eventSpec/AvoEventSpecFetcher");
49
+ var EventValidator_1 = require("./eventSpec/EventValidator");
50
+ var utils_1 = require("./utils");
51
+ var libVersion = require("../package.json").version;
52
+ var AvoInspector = /** @class */ (function () {
53
+ function AvoInspector(options) {
54
+ var _this = this;
42
55
  this.currentBranchId = null;
43
56
  // the constructor does aggressive null/undefined checking because same code paths will be accessible from JS
44
57
  if ((0, utils_1.isValueEmpty)(options.env)) {
45
58
  this.environment = AvoInspectorEnv_1.AvoInspectorEnv.Dev;
46
59
  console.warn("[Avo Inspector] No environment provided. Defaulting to dev.");
47
60
  }
48
- else if (!Object.values(AvoInspectorEnv_1.AvoInspectorEnv).includes(options.env)) {
61
+ else if (Object.values(AvoInspectorEnv_1.AvoInspectorEnv).indexOf(options.env) === -1) {
49
62
  this.environment = AvoInspectorEnv_1.AvoInspectorEnv.Dev;
50
63
  console.warn("[Avo Inspector] Unsupported environment provided. Defaulting to dev. Supported environments - Dev, Staging, Prod.");
51
64
  }
@@ -64,6 +77,9 @@ class AvoInspector {
64
77
  else {
65
78
  this.version = options.version;
66
79
  }
80
+ if (options.publicEncryptionKey) {
81
+ this.publicEncryptionKey = options.publicEncryptionKey;
82
+ }
67
83
  if (this.environment === AvoInspectorEnv_1.AvoInspectorEnv.Dev) {
68
84
  AvoInspector._batchSize = 1;
69
85
  AvoInspector._shouldLog = true;
@@ -73,147 +89,161 @@ class AvoInspector {
73
89
  AvoInspector._batchFlushSeconds = 30;
74
90
  AvoInspector._shouldLog = false;
75
91
  }
76
- AvoInspector.avoStorage = new AvoStorage_1.AvoStorage(AvoInspector._shouldLog, options.suffix != null ? options.suffix : "");
77
- this.publicEncryptionKey = options.publicEncryptionKey;
78
- this.avoNetworkCallsHandler = new AvoNetworkCallsHandler_1.AvoNetworkCallsHandler(this.apiKey, this.environment.toString(), options.appName || "", this.version, libVersion, this.publicEncryptionKey);
79
- this.avoBatcher = new AvoBatcher_1.AvoBatcher(this.avoNetworkCallsHandler);
80
- this.avoDeduplicator = new AvoDeduplicator_1.AvoDeduplicator();
81
- this.streamId = AvoStreamId_1.AvoStreamId.streamId;
82
- // Enable event spec fetching if streamId is present (note: "unknown" is truthy and will trigger initEventSpecModules; see streamId edge case in spec)
83
- if (this.streamId && this.environment !== AvoInspectorEnv_1.AvoInspectorEnv.Prod) {
84
- this._eventSpecReady = this.initEventSpecModules();
85
- }
86
- }
87
- async initEventSpecModules() {
88
- // ORDERING CONSTRAINT: All instance field assignments (this.eventSpecCache,
89
- // this.eventSpecFetcher, this._validateEvent) MUST occur inside the try block,
90
- // before the finally block clears this._eventSpecReady. The finally block sets
91
- // this._eventSpecReady = undefined to signal completion. Concurrent callers that
92
- // await this._eventSpecReady (via ensureEventSpecReady) will resume after the
93
- // finally block executes. If any field assignment were moved to or after the
94
- // finally block, those concurrent callers would find fields unpopulated, creating
95
- // a race condition where they incorrectly proceed as if no event spec is available.
96
92
  try {
97
- const [{ EventSpecCache }, { AvoEventSpecFetcher }, { validateEvent }] = await Promise.all([
98
- Promise.resolve().then(() => require("./eventSpec/AvoEventSpecCache")),
99
- Promise.resolve().then(() => require("./eventSpec/AvoEventSpecFetcher")),
100
- Promise.resolve().then(() => require("./eventSpec/EventValidator"))
101
- ]);
102
- this.eventSpecCache = new EventSpecCache(AvoInspector._shouldLog);
103
- this.eventSpecFetcher = new AvoEventSpecFetcher(AvoInspector._networkTimeout, AvoInspector._shouldLog, this.environment);
104
- this._validateEvent = validateEvent;
105
- if (AvoInspector._shouldLog) {
106
- console.log("[Avo Inspector] Event spec fetching and validation enabled");
107
- if (this.publicEncryptionKey) {
108
- console.log("[Avo Inspector] Property value encryption enabled");
109
- }
110
- }
93
+ AvoInspector.avoStorage = new AvoStorage_1.AvoStorage(AvoInspector._shouldLog);
111
94
  }
112
- catch (error) {
113
- if (AvoInspector._shouldLog) {
114
- console.error("[Avo Inspector] Failed to load event spec modules:", error);
115
- }
116
- }
117
- finally {
118
- this._eventSpecReady = undefined;
95
+ catch (e) {
96
+ console.error("[Avo Inspector] Failed to initialize storage. " +
97
+ "If you are using React Native, make sure @react-native-async-storage/async-storage is installed.", e);
119
98
  }
120
- }
121
- async ensureEventSpecReady() {
122
- if (this.environment === AvoInspectorEnv_1.AvoInspectorEnv.Prod)
123
- return null;
124
- if (this._eventSpecReady)
125
- await this._eventSpecReady;
126
- if (!this.eventSpecCache || !this.eventSpecFetcher || !this.streamId || !this._validateEvent)
127
- return null;
128
- return {
129
- cache: this.eventSpecCache,
130
- fetcher: this.eventSpecFetcher,
131
- validate: this._validateEvent,
132
- streamId: this.streamId,
133
- };
134
- }
135
- async trackSchemaFromEvent(eventName, eventProperties) {
136
- try {
137
- if (this.avoDeduplicator.shouldRegisterEvent(eventName, eventProperties, false)) {
138
- if (AvoInspector.shouldLog) {
139
- console.log("Avo Inspector: supplied event " +
140
- eventName +
141
- " with params " +
142
- JSON.stringify(eventProperties));
143
- }
144
- const eventSchema = await this.extractSchema(eventProperties, false);
145
- // Fetch and validate event spec (sync blocking)
146
- const validationResult = await this.fetchAndValidateEvent(eventName, eventProperties);
147
- if (validationResult) {
148
- // Spec available: merge validation results into schema and send immediately
149
- const schemaWithValidation = this.mergeValidationResults(eventSchema, validationResult);
150
- this.sendEventWithValidation(eventName, schemaWithValidation, null, null, validationResult);
151
- }
152
- else {
153
- // No spec: fall back to batched flow
154
- this.trackSchemaInternal(eventName, eventSchema, null, null);
99
+ var avoNetworkCallsHandler = new AvoNetworkCallsHandler_1.AvoNetworkCallsHandler(this.apiKey, this.environment.toString(), options.appName || "", this.version, libVersion, this.publicEncryptionKey);
100
+ this.avoBatcher = new AvoBatcher_1.AvoBatcher(avoNetworkCallsHandler);
101
+ this.avoDeduplicator = new AvoDeduplicator_1.AvoDeduplicator();
102
+ // Initialize event spec validation infrastructure for dev/staging
103
+ if (this.environment !== AvoInspectorEnv_1.AvoInspectorEnv.Prod) {
104
+ try {
105
+ this.eventSpecCache = new AvoEventSpecCache_1.EventSpecCache(AvoInspector._shouldLog);
106
+ this.eventSpecFetcher = new AvoEventSpecFetcher_1.AvoEventSpecFetcher(5000, AvoInspector._shouldLog, this.environment);
107
+ if (AvoInspector._shouldLog) {
108
+ console.log("[Avo Inspector] Event spec fetching and validation enabled");
155
109
  }
156
- return eventSchema;
157
110
  }
158
- else {
159
- if (AvoInspector.shouldLog) {
160
- console.log("Avo Inspector: Deduplicated event: " + eventName);
161
- }
162
- return [];
111
+ catch (e) {
112
+ console.error("[Avo Inspector] Failed to initialize event spec validation.", e);
163
113
  }
164
114
  }
165
- catch (e) {
166
- console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
167
- return [];
168
- }
115
+ // Fire-and-forget: eagerly initialize the anonymous ID and capture streamId
116
+ AvoStreamId_1.AvoStreamId.initialize().then(function (id) {
117
+ _this.streamId = id;
118
+ }).catch(function (e) {
119
+ console.error("Avo Inspector: failed to initialize anonymous ID.", e);
120
+ });
169
121
  }
170
- async _avoFunctionTrackSchemaFromEvent(eventName, eventProperties, eventId, eventHash) {
171
- try {
172
- if (this.avoDeduplicator.shouldRegisterEvent(eventName, eventProperties, true)) {
173
- if (AvoInspector.shouldLog) {
174
- console.log("Avo Inspector: supplied event " +
175
- eventName +
176
- " with params " +
177
- JSON.stringify(eventProperties));
178
- }
179
- const eventSchema = await this.extractSchema(eventProperties, false);
180
- // Fetch and validate event spec (sync blocking)
181
- const validationResult = await this.fetchAndValidateEvent(eventName, eventProperties);
182
- if (validationResult) {
183
- // Spec available: merge validation results into schema and send immediately
184
- const schemaWithValidation = this.mergeValidationResults(eventSchema, validationResult);
185
- this.sendEventWithValidation(eventName, schemaWithValidation, eventId, eventHash, validationResult);
186
- }
187
- else {
188
- // No spec: fall back to batched flow
189
- this.trackSchemaInternal(eventName, eventSchema, eventId, eventHash);
190
- }
191
- return eventSchema;
122
+ Object.defineProperty(AvoInspector, "batchSize", {
123
+ get: function () {
124
+ return this._batchSize;
125
+ },
126
+ set: function (newSize) {
127
+ if (newSize < 1) {
128
+ this._batchSize = 1;
192
129
  }
193
130
  else {
194
- if (AvoInspector.shouldLog) {
195
- console.log("Avo Inspector: Deduplicated event: " + eventName);
196
- }
197
- return [];
131
+ this._batchSize = newSize;
198
132
  }
199
- }
200
- catch (e) {
201
- console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
202
- return [];
203
- }
204
- }
205
- async trackSchema(eventName, eventSchema) {
133
+ },
134
+ enumerable: false,
135
+ configurable: true
136
+ });
137
+ Object.defineProperty(AvoInspector, "batchFlushSeconds", {
138
+ get: function () {
139
+ return this._batchFlushSeconds;
140
+ },
141
+ enumerable: false,
142
+ configurable: true
143
+ });
144
+ Object.defineProperty(AvoInspector, "shouldLog", {
145
+ get: function () {
146
+ return this._shouldLog;
147
+ },
148
+ set: function (enable) {
149
+ this._shouldLog = enable;
150
+ },
151
+ enumerable: false,
152
+ configurable: true
153
+ });
154
+ AvoInspector.prototype.trackSchemaFromEvent = function (eventName, eventProperties) {
155
+ return __awaiter(this, void 0, void 0, function () {
156
+ var eventSchema, validationResult, schemaWithValidation, e_1;
157
+ return __generator(this, function (_a) {
158
+ switch (_a.label) {
159
+ case 0:
160
+ _a.trys.push([0, 4, , 5]);
161
+ if (!this.avoDeduplicator.shouldRegisterEvent(eventName, eventProperties, false)) return [3 /*break*/, 2];
162
+ if (AvoInspector.shouldLog) {
163
+ console.log("Avo Inspector: supplied event " +
164
+ eventName +
165
+ " with params " +
166
+ JSON.stringify(eventProperties));
167
+ }
168
+ eventSchema = this.extractSchema(eventProperties, false);
169
+ return [4 /*yield*/, this.fetchAndValidateEvent(eventName, eventProperties)];
170
+ case 1:
171
+ validationResult = _a.sent();
172
+ if (validationResult) {
173
+ schemaWithValidation = this.mergeValidationResults(eventSchema, validationResult);
174
+ // Send validated events immediately, bypassing the batcher
175
+ this.sendEventWithValidation(eventName, schemaWithValidation, null, null, validationResult, eventProperties);
176
+ }
177
+ else {
178
+ this.trackSchemaInternal(eventName, eventSchema, null, null, eventProperties);
179
+ }
180
+ return [2 /*return*/, eventSchema];
181
+ case 2:
182
+ if (AvoInspector.shouldLog) {
183
+ console.log("Avo Inspector: Deduplicated event: " + eventName);
184
+ }
185
+ return [2 /*return*/, []];
186
+ case 3: return [3 /*break*/, 5];
187
+ case 4:
188
+ e_1 = _a.sent();
189
+ console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e_1);
190
+ return [2 /*return*/, []];
191
+ case 5: return [2 /*return*/];
192
+ }
193
+ });
194
+ });
195
+ };
196
+ AvoInspector.prototype._avoFunctionTrackSchemaFromEvent = function (eventName, eventProperties, eventId, eventHash) {
197
+ return __awaiter(this, void 0, void 0, function () {
198
+ var eventSchema, validationResult, schemaWithValidation, e_2;
199
+ return __generator(this, function (_a) {
200
+ switch (_a.label) {
201
+ case 0:
202
+ _a.trys.push([0, 4, , 5]);
203
+ if (!this.avoDeduplicator.shouldRegisterEvent(eventName, eventProperties, true)) return [3 /*break*/, 2];
204
+ if (AvoInspector.shouldLog) {
205
+ console.log("Avo Inspector: supplied event " +
206
+ eventName +
207
+ " with params " +
208
+ JSON.stringify(eventProperties));
209
+ }
210
+ eventSchema = this.extractSchema(eventProperties, false);
211
+ return [4 /*yield*/, this.fetchAndValidateEvent(eventName, eventProperties)];
212
+ case 1:
213
+ validationResult = _a.sent();
214
+ if (validationResult) {
215
+ schemaWithValidation = this.mergeValidationResults(eventSchema, validationResult);
216
+ // Send validated events immediately, bypassing the batcher
217
+ this.sendEventWithValidation(eventName, schemaWithValidation, eventId, eventHash, validationResult, eventProperties);
218
+ }
219
+ else {
220
+ this.trackSchemaInternal(eventName, eventSchema, eventId, eventHash, eventProperties);
221
+ }
222
+ return [2 /*return*/, eventSchema];
223
+ case 2:
224
+ if (AvoInspector.shouldLog) {
225
+ console.log("Avo Inspector: Deduplicated event: " + eventName);
226
+ }
227
+ return [2 /*return*/, []];
228
+ case 3: return [3 /*break*/, 5];
229
+ case 4:
230
+ e_2 = _a.sent();
231
+ console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e_2);
232
+ return [2 /*return*/, []];
233
+ case 5: return [2 /*return*/];
234
+ }
235
+ });
236
+ });
237
+ };
238
+ AvoInspector.prototype.trackSchema = function (eventName, eventSchema) {
206
239
  try {
207
- if (await this.avoDeduplicator.shouldRegisterSchemaFromManually(eventName, eventSchema)) {
240
+ if (this.avoDeduplicator.shouldRegisterSchemaFromManually(eventName, eventSchema)) {
208
241
  if (AvoInspector.shouldLog) {
209
242
  console.log("Avo Inspector: supplied event " +
210
243
  eventName +
211
244
  " with schema " +
212
245
  JSON.stringify(eventSchema));
213
246
  }
214
- // For trackSchema we don't have raw properties, so we can't validate
215
- // Just fetch/cache spec for future use and use batched flow
216
- await this.fetchEventSpecIfNeeded(eventName);
217
247
  this.trackSchemaInternal(eventName, eventSchema, null, null);
218
248
  }
219
249
  else {
@@ -225,23 +255,24 @@ class AvoInspector {
225
255
  catch (e) {
226
256
  console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
227
257
  }
228
- }
229
- trackSchemaInternal(eventName, eventSchema, eventId, eventHash) {
258
+ };
259
+ AvoInspector.prototype.trackSchemaInternal = function (eventName, eventSchema, eventId, eventHash, eventProperties) {
230
260
  try {
231
- this.avoBatcher.handleTrackSchema(eventName, eventSchema, eventId, eventHash);
261
+ this.avoBatcher.handleTrackSchema(eventName, eventSchema, eventId, eventHash, eventProperties);
232
262
  }
233
263
  catch (e) {
234
264
  console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
235
265
  }
236
- }
237
- enableLogging(enable) {
266
+ };
267
+ AvoInspector.prototype.enableLogging = function (enable) {
238
268
  AvoInspector._shouldLog = enable;
239
- }
240
- async extractSchema(eventProperties, shouldLogIfEnabled = true) {
269
+ };
270
+ AvoInspector.prototype.extractSchema = function (eventProperties, shouldLogIfEnabled) {
271
+ if (shouldLogIfEnabled === void 0) { shouldLogIfEnabled = true; }
241
272
  try {
242
273
  if (this.avoDeduplicator.hasSeenEventParams(eventProperties, true)) {
243
274
  if (shouldLogIfEnabled && AvoInspector.shouldLog) {
244
- console.warn("Avo Inspector: WARNING! You are trying to extract schema shape that was just reported by your Avo Codegen. " +
275
+ console.warn("Avo Inspector: WARNING! You are trying to extract schema shape that was just reported by your Avo functions. " +
245
276
  "This is an indicator of duplicate inspector reporting. " +
246
277
  "Please reach out to support@avo.app for advice if you are not sure how to handle this.");
247
278
  }
@@ -250,172 +281,125 @@ class AvoInspector {
250
281
  console.log("Avo Inspector: extracting schema from " +
251
282
  JSON.stringify(eventProperties));
252
283
  }
253
- return await AvoSchemaParser_1.AvoSchemaParser.extractSchema(eventProperties, this.publicEncryptionKey, this.environment);
284
+ return AvoSchemaParser_1.AvoSchemaParser.extractSchema(eventProperties);
254
285
  }
255
286
  catch (e) {
256
- console.error("Avo Inspector: something went wrong in extractSchema. Please report to support@avo.app.", e);
287
+ console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
257
288
  return [];
258
289
  }
259
- }
260
- setBatchSize(newBatchSize) {
290
+ };
291
+ AvoInspector.prototype.setBatchSize = function (newBatchSize) {
261
292
  AvoInspector._batchSize = newBatchSize;
262
- }
263
- setBatchFlushSeconds(newBatchFlushSeconds) {
293
+ };
294
+ AvoInspector.prototype.setBatchFlushSeconds = function (newBatchFlushSeconds) {
264
295
  AvoInspector._batchFlushSeconds = newBatchFlushSeconds;
265
- }
296
+ };
266
297
  /**
267
298
  * Handles branch change detection and cache storage for a fetched event spec.
268
- * This logic is shared between fetchEventSpecIfNeeded and fetchAndValidateEvent.
269
299
  */
270
- handleBranchChangeAndCache(specResponse, eventName) {
271
- // Check for branch change
272
- const newBranchId = specResponse.metadata.branchId;
300
+ AvoInspector.prototype.handleBranchChangeAndCache = function (specResponse, eventName) {
301
+ var _a;
302
+ var newBranchId = specResponse.metadata.branchId;
273
303
  if (this.currentBranchId !== null && this.currentBranchId !== newBranchId) {
274
304
  if (AvoInspector.shouldLog) {
275
- console.log(`[Avo Inspector] Branch changed from ${this.currentBranchId} to ${newBranchId}. Flushing cache.`);
305
+ console.log("[Avo Inspector] Branch changed from ".concat(this.currentBranchId, " to ").concat(newBranchId, ". Flushing cache."));
276
306
  }
277
- this.eventSpecCache?.clear();
307
+ (_a = this.eventSpecCache) === null || _a === void 0 ? void 0 : _a.clear();
278
308
  }
279
309
  this.currentBranchId = newBranchId;
280
- // Store in cache
281
310
  if (this.eventSpecCache && this.streamId) {
282
311
  this.eventSpecCache.set(this.apiKey, this.streamId, eventName, specResponse);
283
312
  }
284
- }
285
- /**
286
- * Fetches the event spec if spec fetching is enabled.
287
- * Used by trackSchema when we don't have raw properties to validate.
288
- *
289
- * Note: EventSpec fetching only happens in dev/staging environments.
290
- */
291
- async fetchEventSpecIfNeeded(eventName) {
292
- const spec = await this.ensureEventSpecReady();
293
- if (!spec)
294
- return;
295
- try {
296
- // Check cache first (includes cached empty responses)
297
- if (spec.cache.contains(this.apiKey, spec.streamId, eventName)) {
298
- const cached = spec.cache.get(this.apiKey, spec.streamId, eventName);
299
- if (!cached) {
300
- // Cached empty response — no spec exists for this event
301
- if (AvoInspector.shouldLog) {
302
- console.log(`[Avo Inspector] Cache hit (empty) for event: ${eventName}. Sending without validation.`);
303
- }
304
- }
305
- return;
306
- }
307
- // Cache miss - fetch from API (blocking)
308
- const specResponse = await spec.fetcher.fetch({
309
- apiKey: this.apiKey,
310
- streamId: spec.streamId,
311
- eventName
312
- });
313
- if (specResponse) {
314
- this.handleBranchChangeAndCache(specResponse, eventName);
315
- }
316
- else {
317
- // Cache the empty response so we don't re-fetch
318
- spec.cache.set(this.apiKey, spec.streamId, eventName, null);
319
- if (AvoInspector.shouldLog) {
320
- console.log(`[Avo Inspector] Event spec fetch returned null for event: ${eventName}. Cached empty response.`);
321
- }
322
- }
323
- }
324
- catch (error) {
325
- // Graceful degradation - log but don't fail
326
- if (AvoInspector.shouldLog) {
327
- console.error(`[Avo Inspector] Error fetching event spec for ${eventName}:`, error);
328
- }
329
- }
330
- }
313
+ };
331
314
  /**
332
315
  * Fetches event spec and validates the event against it.
333
316
  * Returns ValidationResult if spec is available, null otherwise.
334
- *
335
- * Note: EventSpec fetching and validation only happens in dev/staging environments.
317
+ * Only runs in dev/staging environments.
336
318
  */
337
- async fetchAndValidateEvent(eventName, eventProperties) {
338
- const spec = await this.ensureEventSpecReady();
339
- if (!spec)
340
- return null;
341
- try {
342
- // Check cache first (includes cached empty responses)
343
- if (spec.cache.contains(this.apiKey, spec.streamId, eventName)) {
344
- const cached = spec.cache.get(this.apiKey, spec.streamId, eventName);
345
- if (cached) {
346
- if (AvoInspector.shouldLog) {
347
- console.log(`[Avo Inspector] Cache hit for event: ${eventName}`);
348
- }
349
- return spec.validate(eventProperties, cached);
319
+ AvoInspector.prototype.fetchAndValidateEvent = function (eventName, eventProperties) {
320
+ return __awaiter(this, void 0, void 0, function () {
321
+ var specResponse, fetched, validationResult, error_1;
322
+ return __generator(this, function (_a) {
323
+ switch (_a.label) {
324
+ case 0:
325
+ // Only fetch specs in dev/staging environments (NOT in production)
326
+ if (this.environment === AvoInspectorEnv_1.AvoInspectorEnv.Prod) {
327
+ return [2 /*return*/, null];
328
+ }
329
+ // Only fetch if we have the required infrastructure
330
+ if (!this.eventSpecCache || !this.eventSpecFetcher || !this.streamId) {
331
+ return [2 /*return*/, null];
332
+ }
333
+ _a.label = 1;
334
+ case 1:
335
+ _a.trys.push([1, 6, , 7]);
336
+ specResponse = this.eventSpecCache.get(this.apiKey, this.streamId, eventName);
337
+ if (!(specResponse === undefined)) return [3 /*break*/, 3];
338
+ return [4 /*yield*/, this.eventSpecFetcher.fetch({
339
+ apiKey: this.apiKey,
340
+ streamId: this.streamId,
341
+ eventName: eventName
342
+ })];
343
+ case 2:
344
+ fetched = _a.sent();
345
+ if (fetched) {
346
+ this.handleBranchChangeAndCache(fetched, eventName);
347
+ specResponse = fetched;
348
+ }
349
+ else {
350
+ // Cache null response to prevent re-fetching
351
+ this.eventSpecCache.set(this.apiKey, this.streamId, eventName, null);
352
+ specResponse = null;
353
+ }
354
+ _a.label = 3;
355
+ case 3:
356
+ if (!specResponse) return [3 /*break*/, 5];
357
+ return [4 /*yield*/, (0, EventValidator_1.validateEvent)(eventProperties, specResponse)];
358
+ case 4:
359
+ validationResult = _a.sent();
360
+ return [2 /*return*/, validationResult];
361
+ case 5: return [2 /*return*/, null];
362
+ case 6:
363
+ error_1 = _a.sent();
364
+ if (AvoInspector.shouldLog) {
365
+ console.error("[Avo Inspector] Error validating event ".concat(eventName, ":"), error_1);
366
+ }
367
+ return [2 /*return*/, null];
368
+ case 7: return [2 /*return*/];
350
369
  }
351
- else {
352
- // Cached empty response — no spec exists for this event
353
- if (AvoInspector.shouldLog) {
354
- console.log(`[Avo Inspector] Cache hit (empty) for event: ${eventName}. Sending without validation.`);
355
- }
356
- return null;
357
- }
358
- }
359
- // Cache miss - fetch from API (blocking)
360
- const specResponse = await spec.fetcher.fetch({
361
- apiKey: this.apiKey,
362
- streamId: spec.streamId,
363
- eventName
364
370
  });
365
- if (specResponse) {
366
- this.handleBranchChangeAndCache(specResponse, eventName);
367
- return spec.validate(eventProperties, specResponse);
368
- }
369
- else {
370
- // Cache the empty response so we don't re-fetch
371
- spec.cache.set(this.apiKey, spec.streamId, eventName, null);
372
- if (AvoInspector.shouldLog) {
373
- console.log(`[Avo Inspector] Event spec fetch returned null for event: ${eventName}. Cached empty response.`);
374
- }
375
- return null;
376
- }
377
- }
378
- catch (error) {
379
- // Graceful degradation - log but don't fail
380
- if (AvoInspector.shouldLog) {
381
- console.error(`[Avo Inspector] Error validating event ${eventName}:`, error);
382
- }
383
- return null;
384
- }
385
- }
371
+ });
372
+ };
386
373
  /**
387
374
  * Merges validation results into the event schema.
388
375
  * Adds failedEventIds or passedEventIds to each property based on validation.
389
- * Recursively merges validation results for nested children.
390
376
  */
391
- mergeValidationResults(eventSchema, validationResult) {
392
- return eventSchema.map((prop) => {
393
- const propValidation = validationResult.propertyResults[prop.propertyName];
394
- return this.mergePropertyValidation(prop, propValidation);
377
+ AvoInspector.prototype.mergeValidationResults = function (eventSchema, validationResult) {
378
+ var _this = this;
379
+ return eventSchema.map(function (prop) {
380
+ var propValidation = validationResult.propertyResults[prop.propertyName];
381
+ return _this.mergePropertyValidation(prop, propValidation);
395
382
  });
396
- }
383
+ };
397
384
  /**
398
385
  * Merges validation result into a single property, recursively handling children.
399
386
  */
400
- mergePropertyValidation(prop, propValidation) {
401
- const result = {
387
+ AvoInspector.prototype.mergePropertyValidation = function (prop, propValidation) {
388
+ var _this = this;
389
+ var result = {
402
390
  propertyName: prop.propertyName,
403
391
  propertyType: prop.propertyType
404
392
  };
405
- if (prop.encryptedPropertyValue) {
406
- result.encryptedPropertyValue = prop.encryptedPropertyValue;
407
- }
408
393
  // Recursively merge validation results into children
409
394
  if (prop.children && Array.isArray(prop.children)) {
410
- result.children = prop.children.map((child) => {
411
- // Children can be strings (for array types) or objects (for nested properties)
395
+ result.children = prop.children.map(function (child) {
396
+ var _a;
412
397
  if (typeof child === 'string') {
413
398
  return child;
414
399
  }
415
400
  if (child && typeof child === 'object' && child.propertyName) {
416
- // Get nested validation result for this child
417
- const childValidation = propValidation?.children?.[child.propertyName];
418
- return this.mergePropertyValidation(child, childValidation);
401
+ var childValidation = (_a = propValidation === null || propValidation === void 0 ? void 0 : propValidation.children) === null || _a === void 0 ? void 0 : _a[child.propertyName];
402
+ return _this.mergePropertyValidation(child, childValidation);
419
403
  }
420
404
  return child;
421
405
  });
@@ -430,45 +414,22 @@ class AvoInspector {
430
414
  }
431
415
  }
432
416
  return result;
433
- }
417
+ };
434
418
  /**
435
- * Sends an event immediately with validation data (bypasses batching).
436
- * Logs validation info if shouldLog is true.
419
+ * Sends a validated event immediately, bypassing the batcher.
420
+ * Matches Android SDK's sendEventWithValidation behavior.
437
421
  */
438
- sendEventWithValidation(eventName, eventSchema, eventId, eventHash, validationResult) {
439
- // Log validation info if shouldLog is enabled
440
- if (AvoInspector.shouldLog) {
441
- const hasFailures = eventSchema.some((p) => p.failedEventIds && p.failedEventIds.length > 0);
442
- if (hasFailures) {
443
- console.log(`[Avo Inspector] Validation failures for event "${eventName}":`, eventSchema
444
- .filter((p) => p.failedEventIds && p.failedEventIds.length > 0)
445
- .map((p) => ({
446
- property: p.propertyName,
447
- failedEventIds: p.failedEventIds
448
- })));
449
- }
450
- }
451
- // Create the event body with validation data
452
- const eventBody = this.avoNetworkCallsHandler.bodyForEventSchemaCall(eventName, eventSchema, eventId, eventHash, validationResult.metadata ?? undefined, validationResult.metadata?.branchId);
453
- // Send immediately (bypass batching)
454
- this.avoNetworkCallsHandler.callInspectorImmediately(eventBody, (error) => {
455
- if (error) {
456
- if (AvoInspector.shouldLog) {
457
- console.error(`[Avo Inspector] Failed to send event "${eventName}" with validation:`, error);
458
- }
459
- // Fallback: add to batch on failure (without validation data)
460
- this.avoBatcher.handleTrackSchema(eventName, eventSchema, eventId, eventHash);
461
- }
462
- else {
463
- if (AvoInspector.shouldLog) {
464
- console.log(`[Avo Inspector] Event "${eventName}" sent successfully with validation`);
465
- }
466
- }
422
+ AvoInspector.prototype.sendEventWithValidation = function (eventName, eventSchema, eventId, eventHash, validationResult, eventProperties) {
423
+ var networkHandler = this.avoBatcher.networkCallsHandler;
424
+ networkHandler.bodyForEventSchemaCall(eventName, eventSchema, eventId, eventHash, eventProperties, validationResult.metadata).then(function (eventBody) {
425
+ networkHandler.reportValidatedEvent(eventBody);
426
+ }).catch(function (e) {
427
+ console.error("Avo Inspector: failed to send validated event.", e);
467
428
  });
468
- }
469
- }
429
+ };
430
+ AvoInspector._batchSize = 30;
431
+ AvoInspector._batchFlushSeconds = 30;
432
+ AvoInspector._shouldLog = false;
433
+ return AvoInspector;
434
+ }());
470
435
  exports.AvoInspector = AvoInspector;
471
- AvoInspector._batchSize = 30;
472
- AvoInspector._batchFlushSeconds = 30;
473
- AvoInspector._shouldLog = false;
474
- AvoInspector._networkTimeout = 2000;