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.
- package/README.md +6 -13
- package/dist/AvoBatcher.js +52 -44
- package/dist/AvoDeduplicator.js +46 -45
- package/dist/AvoEncryption.js +147 -253
- package/dist/AvoInspector.js +295 -334
- package/dist/AvoNetworkCallsHandler.d.ts +6 -0
- package/dist/AvoNetworkCallsHandler.js +180 -136
- package/dist/AvoSchemaParser.js +34 -71
- package/dist/AvoStreamId.js +67 -129
- package/dist/__mocks__/xhr.js +14 -0
- package/dist/__mocks__/xhrError.js +14 -0
- package/dist/__tests__/AvoEncryption.d.ts +1 -0
- package/dist/__tests__/AvoEncryption.js +272 -0
- package/dist/__tests__/AvoEncryptionIntegration.d.ts +1 -0
- package/dist/__tests__/AvoEncryptionIntegration.js +191 -0
- package/dist/__tests__/AvoEventSpecFetcher.d.ts +1 -0
- package/dist/__tests__/AvoEventSpecFetcher.js +377 -0
- package/dist/__tests__/AvoInspector.d.ts +1 -0
- package/dist/__tests__/AvoInspector.js +335 -0
- package/dist/__tests__/Batcher.d.ts +1 -0
- package/dist/__tests__/Batcher.js +214 -0
- package/dist/__tests__/BatcherPublic.d.ts +1 -0
- package/dist/__tests__/BatcherPublic.js +139 -0
- package/dist/__tests__/Deduplicator.d.ts +1 -0
- package/dist/__tests__/Deduplicator.js +190 -0
- package/dist/__tests__/EventSpecCache.d.ts +1 -0
- package/dist/__tests__/EventSpecCache.js +143 -0
- package/dist/__tests__/EventValidator.d.ts +1 -0
- package/dist/__tests__/EventValidator.js +543 -0
- package/dist/__tests__/InstallationId.d.ts +1 -0
- package/dist/__tests__/InstallationId.js +60 -0
- package/dist/__tests__/NetworkCallsHandler.d.ts +1 -0
- package/dist/__tests__/NetworkCallsHandler.js +222 -0
- package/dist/__tests__/NetworkCallsHandlerGzip_test.d.ts +1 -0
- package/dist/__tests__/NetworkCallsHandlerModelA.d.ts +1 -0
- package/dist/__tests__/NetworkCallsHandlerModelA.js +206 -0
- package/dist/__tests__/Parsing.d.ts +1 -0
- package/dist/__tests__/Parsing.js +115 -0
- package/dist/__tests__/Sessions.d.ts +1 -0
- package/dist/__tests__/Sessions.js +10 -0
- package/dist/__tests__/Storage.d.ts +1 -0
- package/dist/__tests__/Storage.js +173 -0
- package/dist/__tests__/StreamId.d.ts +1 -0
- package/dist/__tests__/StreamId.js +153 -0
- package/dist/__tests__/constants.js +48 -0
- package/dist/eventSpec/AvoEventSpecCache.js +94 -82
- package/dist/eventSpec/AvoEventSpecFetcher.js +200 -117
- package/dist/eventSpec/EventValidator.js +460 -304
- package/dist/index.js +1 -1
- package/dist/lite/AvoNetworkCallsHandlerLite.d.ts +6 -0
- package/dist/lite/AvoNetworkCallsHandlerLite.js +110 -1
- package/package.json +2 -2
|
@@ -79,6 +79,12 @@ export declare class AvoNetworkCallsHandler {
|
|
|
79
79
|
private shouldDropBySampling;
|
|
80
80
|
/**
|
|
81
81
|
* Core Inspector API call logic shared by batch and immediate calls.
|
|
82
|
+
*
|
|
83
|
+
* Bodies large enough to be worth it are gzipped (with Content-Encoding: gzip)
|
|
84
|
+
* to cut network volume ~10x. When CompressionStream is unavailable or
|
|
85
|
+
* compression fails, the body is sent uncompressed exactly as before —
|
|
86
|
+
* synchronously in the unavailable case, so legacy timing is preserved.
|
|
82
87
|
*/
|
|
83
88
|
private callInspectorApi;
|
|
89
|
+
private sendTrackingRequest;
|
|
84
90
|
}
|
|
@@ -1,11 +1,48 @@
|
|
|
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.AvoNetworkCallsHandler = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
40
|
+
var AvoGuid_1 = require("./AvoGuid");
|
|
41
|
+
var AvoInspector_1 = require("./AvoInspector");
|
|
42
|
+
var AvoStreamId_1 = require("./AvoStreamId");
|
|
43
|
+
var AvoEncryption_1 = require("./AvoEncryption");
|
|
44
|
+
var AvoNetworkCallsHandler = /** @class */ (function () {
|
|
45
|
+
function AvoNetworkCallsHandler(apiKey, envName, appName, appVersion, libVersion, publicEncryptionKey) {
|
|
9
46
|
this.samplingRate = 1.0;
|
|
10
47
|
this.sending = false;
|
|
11
48
|
this.apiKey = apiKey;
|
|
@@ -15,17 +52,17 @@ class AvoNetworkCallsHandler {
|
|
|
15
52
|
this.libVersion = libVersion;
|
|
16
53
|
this.publicEncryptionKey = publicEncryptionKey;
|
|
17
54
|
}
|
|
18
|
-
callInspectorWithBatchBody(inEvents, onCompleted) {
|
|
55
|
+
AvoNetworkCallsHandler.prototype.callInspectorWithBatchBody = function (inEvents, onCompleted) {
|
|
56
|
+
var _this = this;
|
|
19
57
|
if (this.sending) {
|
|
20
|
-
onCompleted(
|
|
58
|
+
onCompleted("Batch sending cancelled because another batch sending is in progress. Your events will be sent with next batch.");
|
|
21
59
|
return;
|
|
22
60
|
}
|
|
23
|
-
|
|
24
|
-
this.fixStreamIds(events);
|
|
61
|
+
var events = inEvents.filter(function (x) { return x != null; });
|
|
25
62
|
if (events.length === 0) {
|
|
26
63
|
return;
|
|
27
64
|
}
|
|
28
|
-
if (
|
|
65
|
+
if (Math.random() > this.samplingRate) {
|
|
29
66
|
if (AvoInspector_1.AvoInspector.shouldLog) {
|
|
30
67
|
console.log("Avo Inspector: last event schema dropped due to sampling rate.");
|
|
31
68
|
}
|
|
@@ -33,153 +70,160 @@ class AvoNetworkCallsHandler {
|
|
|
33
70
|
}
|
|
34
71
|
if (AvoInspector_1.AvoInspector.shouldLog) {
|
|
35
72
|
console.log("Avo Inspector: events", events);
|
|
36
|
-
events.forEach((event)
|
|
37
|
-
if (event.type === "
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
else if (event.type === "event") {
|
|
41
|
-
console.log("Avo Inspector: sending event " +
|
|
42
|
-
event.eventName +
|
|
43
|
-
" with schema " +
|
|
44
|
-
JSON.stringify(event.eventProperties));
|
|
73
|
+
events.forEach(function (event) {
|
|
74
|
+
if (event.type === "event") {
|
|
75
|
+
var schemaEvent = event;
|
|
76
|
+
console.log("Avo Inspector: sending event " + schemaEvent.eventName + " with schema " + JSON.stringify(schemaEvent.eventProperties));
|
|
45
77
|
}
|
|
46
78
|
});
|
|
47
79
|
}
|
|
48
80
|
this.sending = true;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
event.streamId !== undefined &&
|
|
59
|
-
event.streamId !== "unknown") {
|
|
60
|
-
knownStreamId = event.streamId;
|
|
81
|
+
var xmlhttp = new XMLHttpRequest();
|
|
82
|
+
xmlhttp.open("POST", AvoNetworkCallsHandler.trackingEndpoint, true);
|
|
83
|
+
xmlhttp.setRequestHeader("Content-Type", "application/json");
|
|
84
|
+
xmlhttp.setRequestHeader("Accept", "application/json");
|
|
85
|
+
xmlhttp.timeout = 10000;
|
|
86
|
+
xmlhttp.onload = function () {
|
|
87
|
+
_this.sending = false;
|
|
88
|
+
if (xmlhttp.status != 200) {
|
|
89
|
+
onCompleted("Error ".concat(xmlhttp.status, ": ").concat(xmlhttp.statusText));
|
|
61
90
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
91
|
+
else {
|
|
92
|
+
try {
|
|
93
|
+
var samplingRate = JSON.parse(xmlhttp.response).samplingRate;
|
|
94
|
+
if (samplingRate !== undefined) {
|
|
95
|
+
_this.samplingRate = samplingRate;
|
|
96
|
+
}
|
|
67
97
|
}
|
|
68
|
-
|
|
69
|
-
|
|
98
|
+
catch (_) {
|
|
99
|
+
// Ignore malformed response — sampling rate stays unchanged
|
|
70
100
|
}
|
|
101
|
+
onCompleted(null);
|
|
71
102
|
}
|
|
103
|
+
};
|
|
104
|
+
xmlhttp.onerror = function () {
|
|
105
|
+
_this.sending = false;
|
|
106
|
+
onCompleted("Request failed");
|
|
107
|
+
};
|
|
108
|
+
xmlhttp.ontimeout = function () {
|
|
109
|
+
_this.sending = false;
|
|
110
|
+
onCompleted("Request timed out");
|
|
111
|
+
};
|
|
112
|
+
xmlhttp.send(JSON.stringify(events));
|
|
113
|
+
};
|
|
114
|
+
AvoNetworkCallsHandler.prototype.bodyForEventSchemaCall = function (eventName, eventProperties, eventId, eventHash, eventProps, metadata) {
|
|
115
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
116
|
+
var anonymousId, eventSchemaBody;
|
|
117
|
+
return __generator(this, function (_a) {
|
|
118
|
+
switch (_a.label) {
|
|
119
|
+
case 0: return [4 /*yield*/, AvoStreamId_1.AvoStreamId.initialize()];
|
|
120
|
+
case 1:
|
|
121
|
+
anonymousId = _a.sent();
|
|
122
|
+
eventSchemaBody = this.createBaseCallBody(anonymousId);
|
|
123
|
+
eventSchemaBody.type = "event";
|
|
124
|
+
eventSchemaBody.eventName = eventName;
|
|
125
|
+
// Encrypt property values when encryption is enabled
|
|
126
|
+
if ((0, AvoEncryption_1.shouldEncrypt)(this.envName, this.publicEncryptionKey) &&
|
|
127
|
+
eventProps) {
|
|
128
|
+
eventSchemaBody.eventProperties = (0, AvoEncryption_1.encryptEventProperties)(eventProperties, eventProps, this.publicEncryptionKey);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
eventSchemaBody.eventProperties = eventProperties;
|
|
132
|
+
}
|
|
133
|
+
if (eventId != null) {
|
|
134
|
+
eventSchemaBody.avoFunction = true;
|
|
135
|
+
eventSchemaBody.eventId = eventId;
|
|
136
|
+
eventSchemaBody.eventHash = eventHash;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
eventSchemaBody.avoFunction = false;
|
|
140
|
+
eventSchemaBody.eventId = null;
|
|
141
|
+
eventSchemaBody.eventHash = null;
|
|
142
|
+
}
|
|
143
|
+
// Add streamId and event spec metadata for validated events
|
|
144
|
+
if (metadata) {
|
|
145
|
+
eventSchemaBody.streamId = anonymousId;
|
|
146
|
+
eventSchemaBody.eventSpecMetadata = {};
|
|
147
|
+
if (metadata.schemaId) {
|
|
148
|
+
eventSchemaBody.eventSpecMetadata.schemaId = metadata.schemaId;
|
|
149
|
+
}
|
|
150
|
+
if (metadata.branchId) {
|
|
151
|
+
eventSchemaBody.eventSpecMetadata.branchId = metadata.branchId;
|
|
152
|
+
}
|
|
153
|
+
if (metadata.latestActionId) {
|
|
154
|
+
eventSchemaBody.eventSpecMetadata.latestActionId = metadata.latestActionId;
|
|
155
|
+
}
|
|
156
|
+
if (metadata.sourceId) {
|
|
157
|
+
eventSchemaBody.eventSpecMetadata.sourceId = metadata.sourceId;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return [2 /*return*/, eventSchemaBody];
|
|
161
|
+
}
|
|
162
|
+
});
|
|
72
163
|
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (eventId != null) {
|
|
85
|
-
eventSchemaBody.avoFunction = true;
|
|
86
|
-
eventSchemaBody.eventId = eventId;
|
|
87
|
-
eventSchemaBody.eventHash = eventHash;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
eventSchemaBody.avoFunction = false;
|
|
91
|
-
eventSchemaBody.eventId = null;
|
|
92
|
-
eventSchemaBody.eventHash = null;
|
|
93
|
-
}
|
|
94
|
-
// Set metadata on base body if provided
|
|
95
|
-
if (eventSpecMetadata) {
|
|
96
|
-
eventSchemaBody.eventSpecMetadata = eventSpecMetadata;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Sends a validated event immediately, bypassing the batcher.
|
|
167
|
+
* Matches Android SDK's reportValidatedEvent behavior.
|
|
168
|
+
*/
|
|
169
|
+
AvoNetworkCallsHandler.prototype.reportValidatedEvent = function (eventBody) {
|
|
170
|
+
if (Math.random() > this.samplingRate) {
|
|
171
|
+
if (AvoInspector_1.AvoInspector.shouldLog) {
|
|
172
|
+
console.log("Avo Inspector: validated event dropped due to sampling rate.");
|
|
173
|
+
}
|
|
174
|
+
return;
|
|
97
175
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
176
|
+
if (AvoInspector_1.AvoInspector.shouldLog) {
|
|
177
|
+
console.log("Avo Inspector: sending validated event " +
|
|
178
|
+
eventBody.eventName +
|
|
179
|
+
" with schema " +
|
|
180
|
+
JSON.stringify(eventBody.eventProperties));
|
|
101
181
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
182
|
+
var xmlhttp = new XMLHttpRequest();
|
|
183
|
+
xmlhttp.open("POST", AvoNetworkCallsHandler.trackingEndpoint, true);
|
|
184
|
+
xmlhttp.setRequestHeader("Content-Type", "application/json");
|
|
185
|
+
xmlhttp.setRequestHeader("Accept", "application/json");
|
|
186
|
+
xmlhttp.timeout = 10000;
|
|
187
|
+
xmlhttp.onload = function () {
|
|
188
|
+
if (xmlhttp.status !== 200 && AvoInspector_1.AvoInspector.shouldLog) {
|
|
189
|
+
console.warn("Avo Inspector: validated event response status ".concat(xmlhttp.status));
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
xmlhttp.onerror = function () {
|
|
193
|
+
if (AvoInspector_1.AvoInspector.shouldLog) {
|
|
194
|
+
console.warn("Avo Inspector: failed to send validated event");
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
xmlhttp.ontimeout = function () {
|
|
198
|
+
if (AvoInspector_1.AvoInspector.shouldLog) {
|
|
199
|
+
console.warn("Avo Inspector: validated event report timed out");
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
xmlhttp.send(JSON.stringify([eventBody]));
|
|
203
|
+
};
|
|
204
|
+
AvoNetworkCallsHandler.prototype.createBaseCallBody = function (anonymousId) {
|
|
205
|
+
var body = {
|
|
106
206
|
apiKey: this.apiKey,
|
|
107
207
|
appName: this.appName,
|
|
108
208
|
appVersion: this.appVersion,
|
|
109
209
|
libVersion: this.libVersion,
|
|
110
210
|
env: this.envName,
|
|
111
|
-
libPlatform: "
|
|
211
|
+
libPlatform: "react-native",
|
|
112
212
|
messageId: AvoGuid_1.default.newGuid(),
|
|
113
213
|
trackingId: "",
|
|
114
|
-
createdAt: new Date().toISOString(),
|
|
115
214
|
sessionId: "",
|
|
116
|
-
|
|
117
|
-
|
|
215
|
+
anonymousId: anonymousId,
|
|
216
|
+
createdAt: new Date().toISOString(),
|
|
217
|
+
samplingRate: this.samplingRate,
|
|
118
218
|
};
|
|
119
|
-
if (this.publicEncryptionKey
|
|
219
|
+
if (this.publicEncryptionKey !== null &&
|
|
220
|
+
this.publicEncryptionKey !== undefined &&
|
|
221
|
+
this.publicEncryptionKey.trim().length > 0) {
|
|
120
222
|
body.publicEncryptionKey = this.publicEncryptionKey;
|
|
121
223
|
}
|
|
122
224
|
return body;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
* Note: Does not drop due to sampling - validated events are always sent.
|
|
128
|
-
*/
|
|
129
|
-
callInspectorImmediately(eventBody, onCompleted) {
|
|
130
|
-
// Fix stream ID if needed
|
|
131
|
-
if (eventBody.streamId === "unknown") {
|
|
132
|
-
eventBody.streamId = AvoStreamId_1.AvoStreamId.streamId;
|
|
133
|
-
}
|
|
134
|
-
if (AvoInspector_1.AvoInspector.shouldLog) {
|
|
135
|
-
console.log("Avo Inspector: calling inspector immediately (with validation)", eventBody.eventName);
|
|
136
|
-
console.log("Avo Inspector: event body", eventBody);
|
|
137
|
-
}
|
|
138
|
-
this.callInspectorApi([eventBody], onCompleted);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Check if event should be dropped based on sampling rate.
|
|
142
|
-
*/
|
|
143
|
-
shouldDropBySampling() {
|
|
144
|
-
return Math.random() > this.samplingRate;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Core Inspector API call logic shared by batch and immediate calls.
|
|
148
|
-
*/
|
|
149
|
-
callInspectorApi(events, onCompleted) {
|
|
150
|
-
const xmlhttp = new XMLHttpRequest();
|
|
151
|
-
xmlhttp.open("POST", AvoNetworkCallsHandler.trackingEndpoint, true);
|
|
152
|
-
xmlhttp.setRequestHeader("Content-Type", "text/plain");
|
|
153
|
-
xmlhttp.timeout = AvoInspector_1.AvoInspector.networkTimeout;
|
|
154
|
-
xmlhttp.send(JSON.stringify(events));
|
|
155
|
-
xmlhttp.onload = () => {
|
|
156
|
-
if (xmlhttp.status !== 200) {
|
|
157
|
-
onCompleted(new Error(`Error ${xmlhttp.status}: ${xmlhttp.statusText}`));
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
let response;
|
|
161
|
-
try {
|
|
162
|
-
response = JSON.parse(xmlhttp.response);
|
|
163
|
-
}
|
|
164
|
-
catch (e) {
|
|
165
|
-
onCompleted(new Error(`Failed to parse response: ${e instanceof Error ? e.message : String(e)}`));
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
if (response != null &&
|
|
169
|
-
typeof response.samplingRate === "number" &&
|
|
170
|
-
!isNaN(response.samplingRate)) {
|
|
171
|
-
this.samplingRate = response.samplingRate;
|
|
172
|
-
}
|
|
173
|
-
onCompleted(null);
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
xmlhttp.onerror = () => {
|
|
177
|
-
onCompleted(new Error("Request failed"));
|
|
178
|
-
};
|
|
179
|
-
xmlhttp.ontimeout = () => {
|
|
180
|
-
onCompleted(new Error("Request timed out"));
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
225
|
+
};
|
|
226
|
+
AvoNetworkCallsHandler.trackingEndpoint = "https://api.avo.app/inspector/v1/track";
|
|
227
|
+
return AvoNetworkCallsHandler;
|
|
228
|
+
}());
|
|
184
229
|
exports.AvoNetworkCallsHandler = AvoNetworkCallsHandler;
|
|
185
|
-
AvoNetworkCallsHandler.trackingEndpoint = "https://api.avo.app/inspector/v1/track";
|
package/dist/AvoSchemaParser.js
CHANGED
|
@@ -1,73 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AvoSchemaParser = void 0;
|
|
4
|
-
|
|
4
|
+
var isArray = function (obj) {
|
|
5
5
|
return Object.prototype.toString.call(obj) === "[object Array]";
|
|
6
6
|
};
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Returns true only if we have a valid encryption key and can send encrypted values.
|
|
11
|
-
* If no key is present, returns false and no property values will be sent.
|
|
12
|
-
*/
|
|
13
|
-
static canSendEncryptedValues(publicEncryptionKey, env) {
|
|
14
|
-
const hasEncryptionKey = publicEncryptionKey != null && publicEncryptionKey !== "";
|
|
15
|
-
const isDevOrStaging = env === "dev" || env === "staging";
|
|
16
|
-
return hasEncryptionKey && isDevOrStaging;
|
|
7
|
+
var AvoSchemaParser = /** @class */ (function () {
|
|
8
|
+
function AvoSchemaParser() {
|
|
17
9
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
* Never returns unencrypted values - only encrypted or nothing.
|
|
21
|
-
*/
|
|
22
|
-
static async getEncryptedPropertyValueIfEnabled(propertyValue, canEncrypt, publicEncryptionKey) {
|
|
23
|
-
if (!canEncrypt || !publicEncryptionKey) {
|
|
24
|
-
return undefined; // No encryption key: do not send any property values
|
|
25
|
-
}
|
|
26
|
-
try {
|
|
27
|
-
if (!_encryptValueFn) {
|
|
28
|
-
const { encryptValue } = await Promise.resolve().then(() => require("./AvoEncryption"));
|
|
29
|
-
_encryptValueFn = encryptValue;
|
|
30
|
-
}
|
|
31
|
-
return await _encryptValueFn(propertyValue, publicEncryptionKey); // Only send encrypted values
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
// If encryption fails, log the error but don't fail the entire schema extraction
|
|
35
|
-
console.error("[Avo Inspector] Failed to encrypt property value:", error instanceof Error ? error.message : String(error));
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
static async extractSchema(eventProperties, publicEncryptionKey, env) {
|
|
10
|
+
AvoSchemaParser.extractSchema = function (eventProperties) {
|
|
11
|
+
var _this = this;
|
|
40
12
|
if (eventProperties === null || eventProperties === undefined) {
|
|
41
13
|
return [];
|
|
42
14
|
}
|
|
43
|
-
|
|
44
|
-
const mapping = async (object) => {
|
|
15
|
+
var mapping = function (object) {
|
|
45
16
|
if (isArray(object)) {
|
|
46
|
-
|
|
47
|
-
return
|
|
48
|
-
})
|
|
49
|
-
return
|
|
17
|
+
var list = object.map(function (x) {
|
|
18
|
+
return mapping(x);
|
|
19
|
+
});
|
|
20
|
+
return _this.removeDuplicates(list);
|
|
50
21
|
}
|
|
51
22
|
else if (typeof object === "object") {
|
|
52
|
-
|
|
53
|
-
for (
|
|
23
|
+
var mappedResult = [];
|
|
24
|
+
for (var key in object) {
|
|
54
25
|
if (object.hasOwnProperty(key)) {
|
|
55
|
-
|
|
56
|
-
|
|
26
|
+
var val = object[key];
|
|
27
|
+
var mappedEntry = {
|
|
57
28
|
propertyName: key,
|
|
58
|
-
propertyType:
|
|
29
|
+
propertyType: _this.getPropValueType(val),
|
|
59
30
|
};
|
|
60
31
|
if (typeof val === "object" && val != null) {
|
|
61
|
-
|
|
62
|
-
mappedEntry.children = (await mapping(val));
|
|
63
|
-
}
|
|
64
|
-
else if (val !== undefined) {
|
|
65
|
-
// Primitive properties: encrypt the value if encryption is enabled
|
|
66
|
-
// Skip undefined values - they can't be encrypted and shouldn't be sent
|
|
67
|
-
const encryptedValue = await this.getEncryptedPropertyValueIfEnabled(val, canSendEncryptedValues, publicEncryptionKey);
|
|
68
|
-
if (encryptedValue !== undefined) {
|
|
69
|
-
mappedEntry.encryptedPropertyValue = encryptedValue;
|
|
70
|
-
}
|
|
32
|
+
mappedEntry["children"] = mapping(val);
|
|
71
33
|
}
|
|
72
34
|
mappedResult.push(mappedEntry);
|
|
73
35
|
}
|
|
@@ -75,30 +37,30 @@ class AvoSchemaParser {
|
|
|
75
37
|
return mappedResult;
|
|
76
38
|
}
|
|
77
39
|
else {
|
|
78
|
-
return
|
|
40
|
+
return _this.getPropValueType(object);
|
|
79
41
|
}
|
|
80
42
|
};
|
|
81
|
-
|
|
82
|
-
const mappedEventProps = (await mapping(eventProperties));
|
|
43
|
+
var mappedEventProps = mapping(eventProperties);
|
|
83
44
|
return mappedEventProps;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
45
|
+
};
|
|
46
|
+
AvoSchemaParser.removeDuplicates = function (array) {
|
|
47
|
+
// XXX TODO fix any types
|
|
48
|
+
var primitives = { boolean: {}, number: {}, string: {} };
|
|
49
|
+
var objects = [];
|
|
50
|
+
return array.filter(function (item) {
|
|
51
|
+
var type = typeof item;
|
|
52
|
+
if (type in primitives) {
|
|
91
53
|
return primitives[type].hasOwnProperty(item)
|
|
92
54
|
? false
|
|
93
55
|
: (primitives[type][item] = true);
|
|
94
56
|
}
|
|
95
57
|
else {
|
|
96
|
-
return objects.
|
|
58
|
+
return objects.indexOf(item) >= 0 ? false : objects.push(item);
|
|
97
59
|
}
|
|
98
60
|
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
61
|
+
};
|
|
62
|
+
AvoSchemaParser.getPropValueType = function (propValue) {
|
|
63
|
+
var propType = typeof propValue;
|
|
102
64
|
if (propValue == null) {
|
|
103
65
|
return "null";
|
|
104
66
|
}
|
|
@@ -106,7 +68,7 @@ class AvoSchemaParser {
|
|
|
106
68
|
return "string";
|
|
107
69
|
}
|
|
108
70
|
else if (propType === "number" || propType === "bigint") {
|
|
109
|
-
if ((propValue + "").
|
|
71
|
+
if ((propValue + "").indexOf(".") >= 0) {
|
|
110
72
|
return "float";
|
|
111
73
|
}
|
|
112
74
|
else {
|
|
@@ -127,6 +89,7 @@ class AvoSchemaParser {
|
|
|
127
89
|
else {
|
|
128
90
|
return "unknown";
|
|
129
91
|
}
|
|
130
|
-
}
|
|
131
|
-
|
|
92
|
+
};
|
|
93
|
+
return AvoSchemaParser;
|
|
94
|
+
}());
|
|
132
95
|
exports.AvoSchemaParser = AvoSchemaParser;
|