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.
- package/README.md +10 -0
- package/dist/AvoBatcher.d.ts +9 -3
- package/dist/AvoInspector.d.ts +4 -0
- package/dist/AvoNetworkCallsHandler.d.ts +80 -5
- package/dist/__tests__/UnboundPublicMethods_test.d.ts +1 -0
- package/dist/__tests__/constants.d.ts +2 -1
- package/dist/__tests__/helpers/internalGateway.d.ts +23 -0
- package/dist/eventSpec/AvoEventSpecCache.d.ts +7 -4
- package/dist/eventSpec/AvoEventSpecFetchTypes.d.ts +12 -1
- package/dist/eventSpec/AvoEventSpecFetcher.d.ts +6 -1
- package/dist/index.js +1 -1
- package/dist/lite/AvoBatcherLite.d.ts +9 -3
- package/dist/lite/AvoBatcherLite.js +46 -7
- package/dist/lite/AvoInspectorLite.d.ts +2 -0
- package/dist/lite/AvoInspectorLite.js +95 -15
- package/dist/lite/AvoNetworkCallsHandlerLite.d.ts +79 -5
- package/dist/lite/AvoNetworkCallsHandlerLite.js +300 -20
- package/package.json +10 -1
- package/dist/AvoBatcher.js +0 -87
- package/dist/AvoDeduplicator.js +0 -142
- package/dist/AvoEncryption.js +0 -176
- package/dist/AvoInspector.js +0 -435
- package/dist/AvoNetworkCallsHandler.js +0 -229
- package/dist/AvoSchemaParser.js +0 -95
- package/dist/AvoStreamId.js +0 -82
- package/dist/__mocks__/xhr.js +0 -14
- package/dist/__mocks__/xhrError.js +0 -14
- package/dist/__tests__/AvoEncryption.js +0 -272
- package/dist/__tests__/AvoEncryptionIntegration.js +0 -191
- package/dist/__tests__/AvoEventSpecFetcher.js +0 -377
- package/dist/__tests__/AvoInspector.js +0 -335
- package/dist/__tests__/Batcher.js +0 -214
- package/dist/__tests__/BatcherPublic.js +0 -139
- package/dist/__tests__/Deduplicator.js +0 -190
- package/dist/__tests__/EventSpecCache.js +0 -143
- package/dist/__tests__/EventValidator.js +0 -543
- package/dist/__tests__/InstallationId.js +0 -60
- package/dist/__tests__/NetworkCallsHandler.js +0 -222
- package/dist/__tests__/NetworkCallsHandlerModelA.js +0 -206
- package/dist/__tests__/Parsing.js +0 -115
- package/dist/__tests__/Sessions.d.ts +0 -1
- package/dist/__tests__/Sessions.js +0 -10
- package/dist/__tests__/Storage.d.ts +0 -1
- package/dist/__tests__/Storage.js +0 -173
- package/dist/__tests__/StreamId.d.ts +0 -1
- package/dist/__tests__/StreamId.js +0 -153
- package/dist/__tests__/constants.js +0 -48
- package/dist/esm/AvoBatcher.js +0 -75
- package/dist/esm/AvoDeduplicator.js +0 -137
- package/dist/esm/AvoEncryption.js +0 -277
- package/dist/esm/AvoGuid.js +0 -9
- package/dist/esm/AvoInspector.js +0 -470
- package/dist/esm/AvoInspectorEnv.js +0 -5
- package/dist/esm/AvoNetworkCallsHandler.js +0 -181
- package/dist/esm/AvoSchemaParser.js +0 -128
- package/dist/esm/AvoStorage.js +0 -176
- package/dist/esm/AvoStreamId.js +0 -140
- package/dist/esm/eventSpec/AvoEventSpecCache.js +0 -165
- package/dist/esm/eventSpec/AvoEventSpecFetchTypes.js +0 -6
- package/dist/esm/eventSpec/AvoEventSpecFetcher.js +0 -203
- package/dist/esm/eventSpec/EventValidator.js +0 -687
- package/dist/esm/eventSpec/index.js +0 -4
- package/dist/esm/index.js +0 -3
- package/dist/esm/utils.js +0 -38
- package/dist/esm/version.js +0 -2
- package/dist/eventSpec/AvoEventSpecCache.js +0 -181
- package/dist/eventSpec/AvoEventSpecFetcher.js +0 -290
- package/dist/eventSpec/EventValidator.js +0 -846
- package/dist/eventSpec/index.js +0 -20
- package/dist/version.d.ts +0 -1
- package/dist/version.js +0 -5
- /package/dist/__tests__/{AvoEncryption.d.ts → ApiKeyHeaderInjection_test.d.ts} +0 -0
- /package/dist/__tests__/{AvoEncryptionIntegration.d.ts → BrowserBootstrap_test.d.ts} +0 -0
- /package/dist/__tests__/{AvoEventSpecFetcher.d.ts → EventSpecGatewayCoordinates_test.d.ts} +0 -0
- /package/dist/__tests__/{AvoInspector.d.ts → InFlightQueueGaps_test.d.ts} +0 -0
- /package/dist/__tests__/{Batcher.d.ts → InFlightQueue_test.d.ts} +0 -0
- /package/dist/__tests__/{BatcherPublic.d.ts → NetworkCallsHandlerLite_test.d.ts} +0 -0
- /package/dist/__tests__/{Deduplicator.d.ts → PublicSurface_test.d.ts} +0 -0
- /package/dist/__tests__/{EventSpecCache.d.ts → TrackOptionsIntegration_test.d.ts} +0 -0
- /package/dist/__tests__/{EventValidator.d.ts → TrackOptionsTransport_test.d.ts} +0 -0
- /package/dist/__tests__/{InstallationId.d.ts → TrackingHeaders_test.d.ts} +0 -0
- /package/dist/__tests__/{NetworkCallsHandler.d.ts → V1WireBaseline_test.d.ts} +0 -0
- /package/dist/__tests__/{NetworkCallsHandlerModelA.d.ts → V2QueuedAttribution_test.d.ts} +0 -0
- /package/dist/__tests__/{Parsing.d.ts → V2StopSending_test.d.ts} +0 -0
package/dist/AvoEncryption.js
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* AvoEncryption — React Native ECIES encryption using @noble/ciphers.
|
|
4
|
-
*
|
|
5
|
-
* CRITICAL: React Native's Hermes runtime does NOT have crypto.subtle.
|
|
6
|
-
* This module uses @noble/ciphers/aes gcm() for AES-GCM instead — fully synchronous.
|
|
7
|
-
* Ephemeral key generation and ECDH use @noble/curves/p256.
|
|
8
|
-
*
|
|
9
|
-
* Wire format (MUST match all SDKs):
|
|
10
|
-
* [0x00][65-byte ephemeral pubkey (uncompressed)][16-byte IV][16-byte auth tag][ciphertext]
|
|
11
|
-
* → base64
|
|
12
|
-
*
|
|
13
|
-
* Algorithm:
|
|
14
|
-
* 1. Generate ephemeral P-256 key pair
|
|
15
|
-
* 2. ECDH: ephemeral private key + recipient public key → shared secret (X-coordinate)
|
|
16
|
-
* 3. KDF: SHA-256(shared secret) → 32-byte AES key
|
|
17
|
-
* 4. AES-256-GCM encrypt with random 16-byte IV
|
|
18
|
-
* 5. Serialize: version(1) + ephemeralPubKey(65) + IV(16) + authTag(16) + ciphertext
|
|
19
|
-
* 6. Base64 encode
|
|
20
|
-
*/
|
|
21
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.shouldEncrypt = shouldEncrypt;
|
|
23
|
-
exports.encryptValue = encryptValue;
|
|
24
|
-
exports.encryptEventProperties = encryptEventProperties;
|
|
25
|
-
var p256_1 = require("@noble/curves/p256");
|
|
26
|
-
var aes_1 = require("@noble/ciphers/aes");
|
|
27
|
-
var sha256_1 = require("@noble/hashes/sha256");
|
|
28
|
-
var webcrypto_1 = require("@noble/ciphers/webcrypto");
|
|
29
|
-
/**
|
|
30
|
-
* Converts a hex string to a Uint8Array.
|
|
31
|
-
* Strips optional 0x/0X prefix (matching Android SDK behavior).
|
|
32
|
-
*/
|
|
33
|
-
function hexToBytes(hex) {
|
|
34
|
-
if (hex.startsWith("0x") || hex.startsWith("0X")) {
|
|
35
|
-
hex = hex.substring(2);
|
|
36
|
-
}
|
|
37
|
-
var bytes = new Uint8Array(hex.length / 2);
|
|
38
|
-
for (var i = 0; i < hex.length; i += 2) {
|
|
39
|
-
bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
|
|
40
|
-
}
|
|
41
|
-
return bytes;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Determines whether encryption should be performed.
|
|
45
|
-
*
|
|
46
|
-
* Truth table:
|
|
47
|
-
* dev + key → true
|
|
48
|
-
* staging + key → true
|
|
49
|
-
* prod + key → false
|
|
50
|
-
* dev + null → false
|
|
51
|
-
* dev + empty → false
|
|
52
|
-
*/
|
|
53
|
-
function shouldEncrypt(env, publicEncryptionKey) {
|
|
54
|
-
if (env === "prod")
|
|
55
|
-
return false;
|
|
56
|
-
if (publicEncryptionKey === null ||
|
|
57
|
-
publicEncryptionKey === undefined ||
|
|
58
|
-
publicEncryptionKey.trim().length === 0) {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Encrypts a value using ECIES (P-256 ECDH + AES-256-GCM).
|
|
65
|
-
* Fully synchronous — no async/await.
|
|
66
|
-
*
|
|
67
|
-
* @param value - The plaintext string to encrypt (already JSON-stringified by caller if needed)
|
|
68
|
-
* @param publicKeyHex - The recipient's P-256 public key as a hex string (uncompressed, 04...)
|
|
69
|
-
* @returns Base64-encoded ciphertext in Avo ECIES wire format
|
|
70
|
-
*/
|
|
71
|
-
function encryptValue(value, publicKeyHex) {
|
|
72
|
-
// Fail fast with a helpful message when running in React Native without the polyfill.
|
|
73
|
-
// Node.js and browsers provide crypto natively; only Hermes (RN) lacks it.
|
|
74
|
-
if (!process.env.BROWSER &&
|
|
75
|
-
typeof navigator !== "undefined" && navigator.product === "ReactNative" &&
|
|
76
|
-
(typeof globalThis.crypto === "undefined" || typeof globalThis.crypto.getRandomValues !== "function")) {
|
|
77
|
-
throw new Error("crypto.getRandomValues is not available. " +
|
|
78
|
-
"If you are using React Native, add 'react-native-get-random-values' to your project " +
|
|
79
|
-
"and import it at the top of your entry file (index.js) before any other imports: " +
|
|
80
|
-
"import 'react-native-get-random-values';");
|
|
81
|
-
}
|
|
82
|
-
// 1. Parse recipient public key from hex
|
|
83
|
-
var recipientPublicKeyBytes = hexToBytes(publicKeyHex);
|
|
84
|
-
// 2. Generate ephemeral P-256 key pair
|
|
85
|
-
var ephemeralPrivateKeyBytes = p256_1.p256.utils.randomPrivateKey();
|
|
86
|
-
var ephemeralPublicKeyBytes = p256_1.p256.getPublicKey(ephemeralPrivateKeyBytes, false // uncompressed = 65 bytes (0x04 + 32-byte X + 32-byte Y)
|
|
87
|
-
);
|
|
88
|
-
// 3. ECDH: compute shared secret
|
|
89
|
-
// getSharedSecret returns the full point; extract X-coordinate (last 32 bytes)
|
|
90
|
-
var sharedSecretPoint = p256_1.p256.getSharedSecret(ephemeralPrivateKeyBytes, recipientPublicKeyBytes);
|
|
91
|
-
var sharedSecret = sharedSecretPoint.slice(-32);
|
|
92
|
-
// 4. KDF: SHA-256(sharedSecret) → 32-byte AES key
|
|
93
|
-
var aesKey = (0, sha256_1.sha256)(sharedSecret);
|
|
94
|
-
// 5. Generate random 16-byte IV
|
|
95
|
-
var iv = (0, webcrypto_1.randomBytes)(16);
|
|
96
|
-
// 6. AES-256-GCM encrypt
|
|
97
|
-
var plaintext = new TextEncoder().encode(value);
|
|
98
|
-
var aes = (0, aes_1.gcm)(aesKey, iv);
|
|
99
|
-
var ciphertextWithTag = aes.encrypt(plaintext);
|
|
100
|
-
// @noble/ciphers gcm() returns ciphertext + authTag concatenated
|
|
101
|
-
// Split the LAST 16 bytes as the auth tag
|
|
102
|
-
var authTagLength = 16;
|
|
103
|
-
var ciphertextLength = ciphertextWithTag.length - authTagLength;
|
|
104
|
-
var ciphertext = ciphertextWithTag.slice(0, ciphertextLength);
|
|
105
|
-
var authTag = ciphertextWithTag.slice(ciphertextLength);
|
|
106
|
-
// 7. Serialize: [Version 0x00 (1B)] + [EphemeralPubKey (65B)] + [IV (16B)] + [AuthTag (16B)] + [Ciphertext]
|
|
107
|
-
var resultLength = 1 + ephemeralPublicKeyBytes.length + 16 + 16 + ciphertext.length;
|
|
108
|
-
var result = new Uint8Array(resultLength);
|
|
109
|
-
var offset = 0;
|
|
110
|
-
result[0] = 0x00; // Version byte
|
|
111
|
-
offset += 1;
|
|
112
|
-
result.set(ephemeralPublicKeyBytes, offset);
|
|
113
|
-
offset += ephemeralPublicKeyBytes.length;
|
|
114
|
-
result.set(iv, offset);
|
|
115
|
-
offset += 16;
|
|
116
|
-
result.set(authTag, offset);
|
|
117
|
-
offset += 16;
|
|
118
|
-
result.set(ciphertext, offset);
|
|
119
|
-
// 8. Base64 encode (platform-safe: avoids Buffer which is unavailable in Hermes/React Native)
|
|
120
|
-
var binary = "";
|
|
121
|
-
for (var i = 0; i < result.length; i++) {
|
|
122
|
-
binary += String.fromCharCode(result[i]);
|
|
123
|
-
}
|
|
124
|
-
return btoa(binary);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Encrypts event property values for transmission.
|
|
128
|
-
*
|
|
129
|
-
* Rules:
|
|
130
|
-
* - List-type properties are omitted entirely
|
|
131
|
-
* - On encryption failure: console.warn, omit the property, continue
|
|
132
|
-
* - Returns new array with encryptedPropertyValue set (propertyType/propertyName preserved)
|
|
133
|
-
*/
|
|
134
|
-
function encryptEventProperties(properties, eventProps, publicKeyHex) {
|
|
135
|
-
var result = [];
|
|
136
|
-
var encryptionFailed = false;
|
|
137
|
-
for (var _i = 0, properties_1 = properties; _i < properties_1.length; _i++) {
|
|
138
|
-
var prop = properties_1[_i];
|
|
139
|
-
// Omit list-type properties entirely
|
|
140
|
-
if (prop.propertyType === "list") {
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
// If encryption already failed for this batch, skip remaining properties
|
|
144
|
-
// to avoid spamming the console with the same error
|
|
145
|
-
if (encryptionFailed) {
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
try {
|
|
149
|
-
var value = eventProps[prop.propertyName];
|
|
150
|
-
var jsonValue = JSON.stringify(value === undefined ? null : value);
|
|
151
|
-
var encrypted = encryptValue(jsonValue, publicKeyHex);
|
|
152
|
-
var entry = {
|
|
153
|
-
propertyName: prop.propertyName,
|
|
154
|
-
propertyType: prop.propertyType,
|
|
155
|
-
encryptedPropertyValue: encrypted,
|
|
156
|
-
};
|
|
157
|
-
// Preserve children if present
|
|
158
|
-
if (prop.children !== undefined) {
|
|
159
|
-
entry.children = prop.children;
|
|
160
|
-
}
|
|
161
|
-
// Preserve validation fields if present
|
|
162
|
-
if (prop.failedEventIds !== undefined) {
|
|
163
|
-
entry.failedEventIds = prop.failedEventIds;
|
|
164
|
-
}
|
|
165
|
-
if (prop.passedEventIds !== undefined) {
|
|
166
|
-
entry.passedEventIds = prop.passedEventIds;
|
|
167
|
-
}
|
|
168
|
-
result.push(entry);
|
|
169
|
-
}
|
|
170
|
-
catch (e) {
|
|
171
|
-
encryptionFailed = true;
|
|
172
|
-
console.warn("[Avo Inspector] Encryption failed: ".concat(e instanceof Error ? e.message : String(e), ". Remaining event properties will be omitted from the encrypted payload."));
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return result;
|
|
176
|
-
}
|
package/dist/AvoInspector.js
DELETED
|
@@ -1,435 +0,0 @@
|
|
|
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
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.AvoInspector = void 0;
|
|
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;
|
|
55
|
-
this.currentBranchId = null;
|
|
56
|
-
// the constructor does aggressive null/undefined checking because same code paths will be accessible from JS
|
|
57
|
-
if ((0, utils_1.isValueEmpty)(options.env)) {
|
|
58
|
-
this.environment = AvoInspectorEnv_1.AvoInspectorEnv.Dev;
|
|
59
|
-
console.warn("[Avo Inspector] No environment provided. Defaulting to dev.");
|
|
60
|
-
}
|
|
61
|
-
else if (Object.values(AvoInspectorEnv_1.AvoInspectorEnv).indexOf(options.env) === -1) {
|
|
62
|
-
this.environment = AvoInspectorEnv_1.AvoInspectorEnv.Dev;
|
|
63
|
-
console.warn("[Avo Inspector] Unsupported environment provided. Defaulting to dev. Supported environments - Dev, Staging, Prod.");
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
this.environment = options.env;
|
|
67
|
-
}
|
|
68
|
-
if ((0, utils_1.isValueEmpty)(options.apiKey)) {
|
|
69
|
-
throw new Error("[Avo Inspector] No API key provided. Inspector can't operate without API key.");
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
this.apiKey = options.apiKey;
|
|
73
|
-
}
|
|
74
|
-
if ((0, utils_1.isValueEmpty)(options.version)) {
|
|
75
|
-
throw new Error("[Avo Inspector] No version provided. Many features of Inspector rely on versioning. Please provide comparable string version, i.e. integer or semantic.");
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
this.version = options.version;
|
|
79
|
-
}
|
|
80
|
-
if (options.publicEncryptionKey) {
|
|
81
|
-
this.publicEncryptionKey = options.publicEncryptionKey;
|
|
82
|
-
}
|
|
83
|
-
if (this.environment === AvoInspectorEnv_1.AvoInspectorEnv.Dev) {
|
|
84
|
-
AvoInspector._batchSize = 1;
|
|
85
|
-
AvoInspector._shouldLog = true;
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
AvoInspector._batchSize = 30;
|
|
89
|
-
AvoInspector._batchFlushSeconds = 30;
|
|
90
|
-
AvoInspector._shouldLog = false;
|
|
91
|
-
}
|
|
92
|
-
try {
|
|
93
|
-
AvoInspector.avoStorage = new AvoStorage_1.AvoStorage(AvoInspector._shouldLog);
|
|
94
|
-
}
|
|
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);
|
|
98
|
-
}
|
|
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");
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
catch (e) {
|
|
112
|
-
console.error("[Avo Inspector] Failed to initialize event spec validation.", e);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
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
|
-
});
|
|
121
|
-
}
|
|
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;
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
this._batchSize = newSize;
|
|
132
|
-
}
|
|
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) {
|
|
239
|
-
try {
|
|
240
|
-
if (this.avoDeduplicator.shouldRegisterSchemaFromManually(eventName, eventSchema)) {
|
|
241
|
-
if (AvoInspector.shouldLog) {
|
|
242
|
-
console.log("Avo Inspector: supplied event " +
|
|
243
|
-
eventName +
|
|
244
|
-
" with schema " +
|
|
245
|
-
JSON.stringify(eventSchema));
|
|
246
|
-
}
|
|
247
|
-
this.trackSchemaInternal(eventName, eventSchema, null, null);
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
if (AvoInspector.shouldLog) {
|
|
251
|
-
console.log("Avo Inspector: Deduplicated event: " + eventName);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
catch (e) {
|
|
256
|
-
console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
AvoInspector.prototype.trackSchemaInternal = function (eventName, eventSchema, eventId, eventHash, eventProperties) {
|
|
260
|
-
try {
|
|
261
|
-
this.avoBatcher.handleTrackSchema(eventName, eventSchema, eventId, eventHash, eventProperties);
|
|
262
|
-
}
|
|
263
|
-
catch (e) {
|
|
264
|
-
console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
AvoInspector.prototype.enableLogging = function (enable) {
|
|
268
|
-
AvoInspector._shouldLog = enable;
|
|
269
|
-
};
|
|
270
|
-
AvoInspector.prototype.extractSchema = function (eventProperties, shouldLogIfEnabled) {
|
|
271
|
-
if (shouldLogIfEnabled === void 0) { shouldLogIfEnabled = true; }
|
|
272
|
-
try {
|
|
273
|
-
if (this.avoDeduplicator.hasSeenEventParams(eventProperties, true)) {
|
|
274
|
-
if (shouldLogIfEnabled && AvoInspector.shouldLog) {
|
|
275
|
-
console.warn("Avo Inspector: WARNING! You are trying to extract schema shape that was just reported by your Avo functions. " +
|
|
276
|
-
"This is an indicator of duplicate inspector reporting. " +
|
|
277
|
-
"Please reach out to support@avo.app for advice if you are not sure how to handle this.");
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
if (AvoInspector.shouldLog) {
|
|
281
|
-
console.log("Avo Inspector: extracting schema from " +
|
|
282
|
-
JSON.stringify(eventProperties));
|
|
283
|
-
}
|
|
284
|
-
return AvoSchemaParser_1.AvoSchemaParser.extractSchema(eventProperties);
|
|
285
|
-
}
|
|
286
|
-
catch (e) {
|
|
287
|
-
console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
|
|
288
|
-
return [];
|
|
289
|
-
}
|
|
290
|
-
};
|
|
291
|
-
AvoInspector.prototype.setBatchSize = function (newBatchSize) {
|
|
292
|
-
AvoInspector._batchSize = newBatchSize;
|
|
293
|
-
};
|
|
294
|
-
AvoInspector.prototype.setBatchFlushSeconds = function (newBatchFlushSeconds) {
|
|
295
|
-
AvoInspector._batchFlushSeconds = newBatchFlushSeconds;
|
|
296
|
-
};
|
|
297
|
-
/**
|
|
298
|
-
* Handles branch change detection and cache storage for a fetched event spec.
|
|
299
|
-
*/
|
|
300
|
-
AvoInspector.prototype.handleBranchChangeAndCache = function (specResponse, eventName) {
|
|
301
|
-
var _a;
|
|
302
|
-
var newBranchId = specResponse.metadata.branchId;
|
|
303
|
-
if (this.currentBranchId !== null && this.currentBranchId !== newBranchId) {
|
|
304
|
-
if (AvoInspector.shouldLog) {
|
|
305
|
-
console.log("[Avo Inspector] Branch changed from ".concat(this.currentBranchId, " to ").concat(newBranchId, ". Flushing cache."));
|
|
306
|
-
}
|
|
307
|
-
(_a = this.eventSpecCache) === null || _a === void 0 ? void 0 : _a.clear();
|
|
308
|
-
}
|
|
309
|
-
this.currentBranchId = newBranchId;
|
|
310
|
-
if (this.eventSpecCache && this.streamId) {
|
|
311
|
-
this.eventSpecCache.set(this.apiKey, this.streamId, eventName, specResponse);
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
/**
|
|
315
|
-
* Fetches event spec and validates the event against it.
|
|
316
|
-
* Returns ValidationResult if spec is available, null otherwise.
|
|
317
|
-
* Only runs in dev/staging environments.
|
|
318
|
-
*/
|
|
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*/];
|
|
369
|
-
}
|
|
370
|
-
});
|
|
371
|
-
});
|
|
372
|
-
};
|
|
373
|
-
/**
|
|
374
|
-
* Merges validation results into the event schema.
|
|
375
|
-
* Adds failedEventIds or passedEventIds to each property based on validation.
|
|
376
|
-
*/
|
|
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);
|
|
382
|
-
});
|
|
383
|
-
};
|
|
384
|
-
/**
|
|
385
|
-
* Merges validation result into a single property, recursively handling children.
|
|
386
|
-
*/
|
|
387
|
-
AvoInspector.prototype.mergePropertyValidation = function (prop, propValidation) {
|
|
388
|
-
var _this = this;
|
|
389
|
-
var result = {
|
|
390
|
-
propertyName: prop.propertyName,
|
|
391
|
-
propertyType: prop.propertyType
|
|
392
|
-
};
|
|
393
|
-
// Recursively merge validation results into children
|
|
394
|
-
if (prop.children && Array.isArray(prop.children)) {
|
|
395
|
-
result.children = prop.children.map(function (child) {
|
|
396
|
-
var _a;
|
|
397
|
-
if (typeof child === 'string') {
|
|
398
|
-
return child;
|
|
399
|
-
}
|
|
400
|
-
if (child && typeof child === 'object' && child.propertyName) {
|
|
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);
|
|
403
|
-
}
|
|
404
|
-
return child;
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
// Add validation result for this property
|
|
408
|
-
if (propValidation) {
|
|
409
|
-
if (propValidation.failedEventIds) {
|
|
410
|
-
result.failedEventIds = propValidation.failedEventIds;
|
|
411
|
-
}
|
|
412
|
-
if (propValidation.passedEventIds) {
|
|
413
|
-
result.passedEventIds = propValidation.passedEventIds;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
return result;
|
|
417
|
-
};
|
|
418
|
-
/**
|
|
419
|
-
* Sends a validated event immediately, bypassing the batcher.
|
|
420
|
-
* Matches Android SDK's sendEventWithValidation behavior.
|
|
421
|
-
*/
|
|
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);
|
|
428
|
-
});
|
|
429
|
-
};
|
|
430
|
-
AvoInspector._batchSize = 30;
|
|
431
|
-
AvoInspector._batchFlushSeconds = 30;
|
|
432
|
-
AvoInspector._shouldLog = false;
|
|
433
|
-
return AvoInspector;
|
|
434
|
-
}());
|
|
435
|
-
exports.AvoInspector = AvoInspector;
|