avo-inspector 2.2.0 → 2.2.2-alpha.2
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/CHANGELOG.md +34 -1
- package/README.md +130 -0
- package/bin/avo-inspector.js +97 -0
- package/dist/AvoBatcher.d.ts +4 -11
- package/dist/AvoEncryption.d.ts +33 -0
- package/dist/AvoInspector.d.ts +35 -6
- package/dist/AvoNetworkCallsHandler.d.ts +42 -12
- package/dist/AvoSchemaParser.d.ts +12 -5
- package/dist/browser.js.LICENSE.txt +5 -0
- package/dist/eventSpec/AvoEventSpecCache.d.ts +73 -0
- package/dist/eventSpec/AvoEventSpecFetchTypes.d.ts +141 -0
- package/dist/eventSpec/AvoEventSpecFetcher.d.ts +54 -0
- package/dist/eventSpec/EventValidator.d.ts +34 -0
- package/dist/eventSpec/cache.d.ts +73 -0
- package/dist/eventSpec/index.d.ts +4 -0
- package/dist/eventSpec/types.d.ts +74 -0
- package/dist/index.js +2 -1
- package/dist/index.js.LICENSE.txt +5 -0
- package/dist-browser/AvoAnonymousId.d.ts +26 -0
- package/dist-browser/AvoBatcher.d.ts +26 -0
- package/dist-browser/AvoDeduplicator.d.ts +20 -0
- package/dist-browser/AvoEncryption.d.ts +33 -0
- package/dist-browser/AvoGuid.d.ts +3 -0
- package/dist-browser/AvoInspector.d.ts +78 -0
- package/dist-browser/AvoInspectorEnv.d.ts +7 -0
- package/dist-browser/AvoNetworkCallsHandler.d.ts +74 -0
- package/dist-browser/AvoSchemaParser.d.ts +20 -0
- package/dist-browser/AvoStorage.d.ts +22 -0
- package/dist-browser/__mocks__/xhr.d.ts +12 -0
- package/dist-browser/__mocks__/xhrError.d.ts +12 -0
- package/dist-browser/__tests__/AnonymousId_test.d.ts +1 -0
- package/dist-browser/__tests__/AvoEncryption_test.d.ts +1 -0
- package/dist-browser/__tests__/AvoInspectorEventSpec_test.d.ts +1 -0
- package/dist-browser/__tests__/AvoInspector_test.d.ts +1 -0
- package/dist-browser/__tests__/BatcherPublic_test.d.ts +1 -0
- package/dist-browser/__tests__/Batcher_test.d.ts +1 -0
- package/dist-browser/__tests__/Deduplicator_test.d.ts +1 -0
- package/dist-browser/__tests__/EncryptedPropertyTracking_test.d.ts +1 -0
- package/dist-browser/__tests__/EventSpecCache_test.d.ts +1 -0
- package/dist-browser/__tests__/EventSpecFetcher_test.d.ts +1 -0
- package/dist-browser/__tests__/EventValidator_test.d.ts +1 -0
- package/dist-browser/__tests__/NetworkCallsHandler_test.d.ts +1 -0
- package/dist-browser/__tests__/Parsing_test.d.ts +1 -0
- package/dist-browser/__tests__/Storage_test.d.ts +1 -0
- package/dist-browser/__tests__/ValidationIntegration_test.d.ts +1 -0
- package/dist-browser/__tests__/constants.d.ts +36 -0
- package/dist-browser/__tests__/helpers/encryptionHelpers.d.ts +13 -0
- package/dist-browser/__tests__/helpers/mockFactories.d.ts +49 -0
- package/dist-browser/eventSpec/AvoEventSpecCache.d.ts +73 -0
- package/dist-browser/eventSpec/AvoEventSpecFetchTypes.d.ts +109 -0
- package/dist-browser/eventSpec/AvoEventSpecFetcher.d.ts +55 -0
- package/dist-browser/eventSpec/EventValidator.d.ts +90 -0
- package/dist-browser/eventSpec/index.d.ts +4 -0
- package/dist-browser/index.d.ts +2 -0
- package/dist-browser/utils.d.ts +3 -0
- package/dist-native/AvoBatcher.d.ts +24 -0
- package/dist-native/AvoBatcher.js +82 -0
- package/dist-native/AvoDeduplicator.d.ts +36 -0
- package/dist-native/AvoDeduplicator.js +142 -0
- package/dist-native/AvoGuid.d.ts +3 -0
- package/dist-native/AvoGuid.js +14 -0
- package/dist-native/AvoInspector.d.ts +52 -0
- package/dist-native/AvoInspector.js +220 -0
- package/dist-native/AvoInspectorEnv.d.ts +7 -0
- package/dist-native/AvoInspectorEnv.js +8 -0
- package/dist-native/AvoInstallationId.d.ts +5 -0
- package/dist-native/AvoInstallationId.js +36 -0
- package/dist-native/AvoNetworkCallsHandler.d.ts +48 -0
- package/dist-native/AvoNetworkCallsHandler.js +142 -0
- package/dist-native/AvoSchemaParser.d.ts +11 -0
- package/dist-native/AvoSchemaParser.js +95 -0
- package/dist-native/AvoSessionTracker.d.ts +15 -0
- package/dist-native/AvoSessionTracker.js +104 -0
- package/dist-native/AvoStorage.d.ts +22 -0
- package/dist-native/AvoStorage.js +336 -0
- package/dist-native/__mocks__/xhr.d.ts +12 -0
- package/dist-native/__mocks__/xhr.js +14 -0
- package/dist-native/__mocks__/xhrError.d.ts +12 -0
- package/dist-native/__mocks__/xhrError.js +14 -0
- package/dist-native/__tests__/AvoInspector.d.ts +1 -0
- package/dist-native/__tests__/AvoInspector.js +207 -0
- package/dist-native/__tests__/Batcher.d.ts +1 -0
- package/dist-native/__tests__/Batcher.js +280 -0
- package/dist-native/__tests__/BatcherPublic.d.ts +1 -0
- package/dist-native/__tests__/BatcherPublic.js +82 -0
- package/dist-native/__tests__/Deduplicator.d.ts +1 -0
- package/dist-native/__tests__/Deduplicator.js +111 -0
- package/dist-native/__tests__/InstallationId.d.ts +1 -0
- package/dist-native/__tests__/InstallationId.js +40 -0
- package/dist-native/__tests__/NetworkCallsHandler.d.ts +1 -0
- package/dist-native/__tests__/NetworkCallsHandler.js +132 -0
- package/dist-native/__tests__/Parsing.d.ts +1 -0
- package/dist-native/__tests__/Parsing.js +115 -0
- package/dist-native/__tests__/Sessions.d.ts +1 -0
- package/dist-native/__tests__/Sessions.js +179 -0
- package/dist-native/__tests__/Storage.d.ts +1 -0
- package/dist-native/__tests__/Storage.js +173 -0
- package/dist-native/__tests__/constants.d.ts +36 -0
- package/dist-native/__tests__/constants.js +47 -0
- package/dist-native/index.d.ts +2 -0
- package/dist-native/index.js +7 -0
- package/dist-native/utils.d.ts +3 -0
- package/dist-native/utils.js +42 -0
- package/jest.config.js +6 -0
- package/package.json +8 -2
- package/webpack.browserConfig.js +1 -1
- package/webpack.config.js +1 -1
- package/.claude/settings.local.json +0 -9
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EventValidator - Client-side validation of tracking events against the Avo Tracking Plan.
|
|
3
|
+
*
|
|
4
|
+
* This module handles:
|
|
5
|
+
* 1. Matching: Identifying the most likely Event and Variant from specs
|
|
6
|
+
* 2. Validation: Checking runtime properties against the matched spec rules
|
|
7
|
+
*/
|
|
8
|
+
import type { EventSpecResponse, EventSpec, EventSpecMetadata, VariantSpec } from "./AvoEventSpecFetchTypes";
|
|
9
|
+
/**
|
|
10
|
+
* Validation issue codes for client-side validation.
|
|
11
|
+
*/
|
|
12
|
+
export type ValidationIssueCode = "RequiredMissing" | "ValueBelowMin" | "ValueAboveMax" | "RegexMismatch" | "NotInAllowedValues" | "UnexpectedProperty" | "UnexpectedEvent" | "TypeMismatch";
|
|
13
|
+
/**
|
|
14
|
+
* Represents a validation issue found during event validation.
|
|
15
|
+
*
|
|
16
|
+
* Note: We do NOT include the received value to avoid sending user data to the backend.
|
|
17
|
+
* The backend can correlate issues with encrypted values via propertyName matching
|
|
18
|
+
* against eventProperties.encryptedPropertyValue in the payload.
|
|
19
|
+
*/
|
|
20
|
+
export interface ValidationIssue {
|
|
21
|
+
/** The type of validation issue */
|
|
22
|
+
code: ValidationIssueCode;
|
|
23
|
+
/** Property ID (preferred over name) */
|
|
24
|
+
propertyId?: string;
|
|
25
|
+
/** Property name - used to correlate with encryptedPropertyValue in eventProperties */
|
|
26
|
+
propertyName?: string;
|
|
27
|
+
/** Expected value for the validation rule (from spec, not user data) */
|
|
28
|
+
expected?: string | number | boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Result of the validation process.
|
|
32
|
+
*/
|
|
33
|
+
export interface ValidationResult {
|
|
34
|
+
/** ID of the matched event, null if no match found */
|
|
35
|
+
eventId: string | null;
|
|
36
|
+
/** ID of the matched variant, null if base event or no match */
|
|
37
|
+
variantId: string | null;
|
|
38
|
+
/** Event spec metadata from the response */
|
|
39
|
+
eventSpecMetadata: EventSpecMetadata;
|
|
40
|
+
/** List of all validation issues found */
|
|
41
|
+
validationErrors: ValidationIssue[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Runtime property value - can be any JSON-compatible type
|
|
45
|
+
*/
|
|
46
|
+
export type RuntimePropertyValue = string | number | boolean | null | undefined | object | Array<any>;
|
|
47
|
+
/**
|
|
48
|
+
* Runtime properties map
|
|
49
|
+
*/
|
|
50
|
+
export type RuntimeProperties = Record<string, RuntimePropertyValue>;
|
|
51
|
+
/**
|
|
52
|
+
* Internal match result for scoring
|
|
53
|
+
*/
|
|
54
|
+
interface MatchCandidate {
|
|
55
|
+
event: EventSpec;
|
|
56
|
+
variant: VariantSpec | null;
|
|
57
|
+
score: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Validates a runtime event against the EventSpecResponse.
|
|
61
|
+
*
|
|
62
|
+
* @param eventName - The event name observed at runtime
|
|
63
|
+
* @param properties - The properties observed at runtime
|
|
64
|
+
* @param specResponse - The EventSpecResponse from the backend
|
|
65
|
+
* @returns ValidationResult with match info and any validation errors
|
|
66
|
+
*/
|
|
67
|
+
export declare function validateEvent(eventName: string, properties: RuntimeProperties, specResponse: EventSpecResponse): ValidationResult;
|
|
68
|
+
/**
|
|
69
|
+
* Finds the closest matching Event and Variant for the runtime data.
|
|
70
|
+
*
|
|
71
|
+
* @param eventName - Runtime event name
|
|
72
|
+
* @param properties - Runtime properties
|
|
73
|
+
* @param events - Array of EventSpecs to match against
|
|
74
|
+
* @returns The best matching event and variant, or null if no match
|
|
75
|
+
*/
|
|
76
|
+
export declare function findClosestMatch(eventName: string, properties: RuntimeProperties, events: EventSpec[]): MatchCandidate | null;
|
|
77
|
+
/**
|
|
78
|
+
* Validates runtime properties against the matched event and variant specs.
|
|
79
|
+
*
|
|
80
|
+
* @param properties - Runtime properties
|
|
81
|
+
* @param event - Matched EventSpec
|
|
82
|
+
* @param variant - Matched VariantSpec (or null for base event)
|
|
83
|
+
* @returns Array of validation issues found
|
|
84
|
+
*/
|
|
85
|
+
export declare function validateProperties(properties: RuntimeProperties, event: EventSpec, variant: VariantSpec | null): ValidationIssue[];
|
|
86
|
+
/**
|
|
87
|
+
* Quick check if an event exists in the spec (without full validation).
|
|
88
|
+
*/
|
|
89
|
+
export declare function eventExistsInSpec(eventName: string, specResponse: EventSpecResponse): boolean;
|
|
90
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AvoNetworkCallsHandler } from "./AvoNetworkCallsHandler";
|
|
2
|
+
export interface AvoBatcherType {
|
|
3
|
+
handleSessionStarted(): void;
|
|
4
|
+
handleTrackSchema(eventName: string, schema: Array<{
|
|
5
|
+
propertyName: string;
|
|
6
|
+
propertyType: string;
|
|
7
|
+
children?: any;
|
|
8
|
+
}>, eventId: string | null, eventHash: string | null): void;
|
|
9
|
+
}
|
|
10
|
+
export declare class AvoBatcher implements AvoBatcherType {
|
|
11
|
+
private events;
|
|
12
|
+
private batchFlushAttemptTimestamp;
|
|
13
|
+
private networkCallsHandler;
|
|
14
|
+
constructor(networkCallsHandler: AvoNetworkCallsHandler);
|
|
15
|
+
handleSessionStarted(): void;
|
|
16
|
+
handleTrackSchema(eventName: string, schema: Array<{
|
|
17
|
+
propertyName: string;
|
|
18
|
+
propertyType: string;
|
|
19
|
+
children?: any;
|
|
20
|
+
}>, eventId: string | null, eventHash: string | null): void;
|
|
21
|
+
private checkIfBatchNeedsToBeSent;
|
|
22
|
+
private saveEvents;
|
|
23
|
+
static get cacheKey(): string;
|
|
24
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AvoBatcher = void 0;
|
|
4
|
+
var AvoInspector_1 = require("./AvoInspector");
|
|
5
|
+
var AvoBatcher = /** @class */ (function () {
|
|
6
|
+
function AvoBatcher(networkCallsHandler) {
|
|
7
|
+
var _this = this;
|
|
8
|
+
this.events = [];
|
|
9
|
+
this.networkCallsHandler = networkCallsHandler;
|
|
10
|
+
this.batchFlushAttemptTimestamp = Date.now();
|
|
11
|
+
AvoInspector_1.AvoInspector.avoStorage
|
|
12
|
+
.getItemAsync(AvoBatcher.cacheKey)
|
|
13
|
+
.then(function (savedEvents) {
|
|
14
|
+
if (savedEvents !== null) {
|
|
15
|
+
var nonNullSavedEvents = savedEvents.filter(function (event) { return event !== null; });
|
|
16
|
+
_this.events = _this.events.concat(nonNullSavedEvents);
|
|
17
|
+
_this.checkIfBatchNeedsToBeSent();
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
AvoBatcher.prototype.handleSessionStarted = function () {
|
|
22
|
+
this.events.push(this.networkCallsHandler.bodyForSessionStartedCall());
|
|
23
|
+
this.saveEvents();
|
|
24
|
+
this.checkIfBatchNeedsToBeSent();
|
|
25
|
+
};
|
|
26
|
+
AvoBatcher.prototype.handleTrackSchema = function (eventName, schema, eventId, eventHash) {
|
|
27
|
+
this.events.push(this.networkCallsHandler.bodyForEventSchemaCall(eventName, schema, eventId, eventHash));
|
|
28
|
+
this.saveEvents();
|
|
29
|
+
if (AvoInspector_1.AvoInspector.shouldLog) {
|
|
30
|
+
console.log("Avo Inspector: saved event " +
|
|
31
|
+
eventName +
|
|
32
|
+
" with schema " +
|
|
33
|
+
JSON.stringify(schema));
|
|
34
|
+
}
|
|
35
|
+
this.checkIfBatchNeedsToBeSent();
|
|
36
|
+
};
|
|
37
|
+
AvoBatcher.prototype.checkIfBatchNeedsToBeSent = function () {
|
|
38
|
+
var batchSize = this.events.length;
|
|
39
|
+
var now = Date.now();
|
|
40
|
+
var timeSinceLastFlushAttempt = now - this.batchFlushAttemptTimestamp;
|
|
41
|
+
var sendBySize = batchSize % AvoInspector_1.AvoInspector.batchSize == 0;
|
|
42
|
+
var sendByTime = timeSinceLastFlushAttempt >= AvoInspector_1.AvoInspector.batchFlushSeconds * 1000;
|
|
43
|
+
var avoBatcher = this;
|
|
44
|
+
if (sendBySize || sendByTime) {
|
|
45
|
+
this.batchFlushAttemptTimestamp = now;
|
|
46
|
+
var sendingEvents_1 = avoBatcher.events;
|
|
47
|
+
avoBatcher.events = [];
|
|
48
|
+
this.networkCallsHandler.callInspectorWithBatchBody(sendingEvents_1, function (error) {
|
|
49
|
+
if (error != null) {
|
|
50
|
+
avoBatcher.events = avoBatcher.events.concat(sendingEvents_1);
|
|
51
|
+
if (AvoInspector_1.AvoInspector.shouldLog) {
|
|
52
|
+
console.log("Avo Inspector: batch sending failed: " +
|
|
53
|
+
error +
|
|
54
|
+
". We will attempt to send your schemas with next batch");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
if (AvoInspector_1.AvoInspector.shouldLog) {
|
|
59
|
+
console.log("Avo Inspector: batch sent successfully.");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
avoBatcher.saveEvents();
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
AvoBatcher.prototype.saveEvents = function () {
|
|
67
|
+
if (this.events.length > 1000) {
|
|
68
|
+
var extraElements = this.events.length - 1000;
|
|
69
|
+
this.events.splice(0, extraElements);
|
|
70
|
+
}
|
|
71
|
+
AvoInspector_1.AvoInspector.avoStorage.setItem(AvoBatcher.cacheKey, this.events);
|
|
72
|
+
};
|
|
73
|
+
Object.defineProperty(AvoBatcher, "cacheKey", {
|
|
74
|
+
get: function () {
|
|
75
|
+
return "AvoInspectorEvents";
|
|
76
|
+
},
|
|
77
|
+
enumerable: false,
|
|
78
|
+
configurable: true
|
|
79
|
+
});
|
|
80
|
+
return AvoBatcher;
|
|
81
|
+
}());
|
|
82
|
+
exports.AvoBatcher = AvoBatcher;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare class AvoDeduplicator {
|
|
2
|
+
avoFunctionsEvents: {
|
|
3
|
+
[time: number]: string;
|
|
4
|
+
};
|
|
5
|
+
manualEvents: {
|
|
6
|
+
[time: number]: string;
|
|
7
|
+
};
|
|
8
|
+
avoFunctionsEventsParams: {
|
|
9
|
+
[eventName: string]: {
|
|
10
|
+
[propName: string]: any;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
manualEventsParams: {
|
|
14
|
+
[eventName: string]: {
|
|
15
|
+
[propName: string]: any;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
shouldRegisterEvent(eventName: string, params: {
|
|
19
|
+
[propName: string]: any;
|
|
20
|
+
}, fromAvoFunction: boolean): boolean;
|
|
21
|
+
private hasSameEventAs;
|
|
22
|
+
private lookForEventIn;
|
|
23
|
+
hasSeenEventParams(params: {
|
|
24
|
+
[propName: string]: any;
|
|
25
|
+
}, checkInAvoFunctions: boolean): boolean;
|
|
26
|
+
private lookForEventParamsIn;
|
|
27
|
+
shouldRegisterSchemaFromManually(eventName: string, eventSchema: Array<{
|
|
28
|
+
propertyName: string;
|
|
29
|
+
propertyType: string;
|
|
30
|
+
children?: any;
|
|
31
|
+
}>): boolean;
|
|
32
|
+
private hasSameShapeInAvoFunctionsAs;
|
|
33
|
+
private lookForEventSchemaIn;
|
|
34
|
+
private clearOldEvents;
|
|
35
|
+
private _clearEvents;
|
|
36
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AvoDeduplicator = void 0;
|
|
4
|
+
var AvoSchemaParser_1 = require("./AvoSchemaParser");
|
|
5
|
+
var utils_1 = require("./utils");
|
|
6
|
+
var AvoDeduplicator = /** @class */ (function () {
|
|
7
|
+
function AvoDeduplicator() {
|
|
8
|
+
this.avoFunctionsEvents = {};
|
|
9
|
+
this.manualEvents = {};
|
|
10
|
+
this.avoFunctionsEventsParams = {};
|
|
11
|
+
this.manualEventsParams = {};
|
|
12
|
+
}
|
|
13
|
+
AvoDeduplicator.prototype.shouldRegisterEvent = function (eventName, params, fromAvoFunction) {
|
|
14
|
+
this.clearOldEvents();
|
|
15
|
+
if (fromAvoFunction) {
|
|
16
|
+
this.avoFunctionsEvents[Date.now()] = eventName;
|
|
17
|
+
this.avoFunctionsEventsParams[eventName] = params;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
this.manualEvents[Date.now()] = eventName;
|
|
21
|
+
this.manualEventsParams[eventName] = params;
|
|
22
|
+
}
|
|
23
|
+
var checkInAvoFunctions = !fromAvoFunction;
|
|
24
|
+
return !this.hasSameEventAs(eventName, params, checkInAvoFunctions);
|
|
25
|
+
};
|
|
26
|
+
AvoDeduplicator.prototype.hasSameEventAs = function (eventName, params, checkInAvoFunctions) {
|
|
27
|
+
var result = false;
|
|
28
|
+
if (checkInAvoFunctions) {
|
|
29
|
+
if (this.lookForEventIn(eventName, params, this.avoFunctionsEventsParams)) {
|
|
30
|
+
result = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (this.lookForEventIn(eventName, params, this.manualEventsParams)) {
|
|
35
|
+
result = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (result) {
|
|
39
|
+
delete this.avoFunctionsEventsParams[eventName];
|
|
40
|
+
delete this.manualEventsParams[eventName];
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
AvoDeduplicator.prototype.lookForEventIn = function (eventName, params, eventsStorage) {
|
|
45
|
+
for (var otherEventName in eventsStorage) {
|
|
46
|
+
if (eventsStorage.hasOwnProperty(otherEventName)) {
|
|
47
|
+
if (otherEventName === eventName) {
|
|
48
|
+
var otherParams = eventsStorage[eventName];
|
|
49
|
+
if (otherParams && (0, utils_1.deepEquals)(params, otherParams)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
};
|
|
57
|
+
AvoDeduplicator.prototype.hasSeenEventParams = function (params, checkInAvoFunctions) {
|
|
58
|
+
var result = false;
|
|
59
|
+
if (checkInAvoFunctions) {
|
|
60
|
+
if (this.lookForEventParamsIn(params, this.avoFunctionsEventsParams)) {
|
|
61
|
+
result = true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
if (this.lookForEventParamsIn(params, this.manualEventsParams)) {
|
|
66
|
+
result = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
};
|
|
71
|
+
AvoDeduplicator.prototype.lookForEventParamsIn = function (params, eventsStorage) {
|
|
72
|
+
for (var otherEventName in eventsStorage) {
|
|
73
|
+
if (eventsStorage.hasOwnProperty(otherEventName)) {
|
|
74
|
+
var otherParams = eventsStorage[otherEventName];
|
|
75
|
+
if (otherParams && (0, utils_1.deepEquals)(params, otherParams)) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
};
|
|
82
|
+
AvoDeduplicator.prototype.shouldRegisterSchemaFromManually = function (eventName, eventSchema) {
|
|
83
|
+
this.clearOldEvents();
|
|
84
|
+
return !this.hasSameShapeInAvoFunctionsAs(eventName, eventSchema);
|
|
85
|
+
};
|
|
86
|
+
AvoDeduplicator.prototype.hasSameShapeInAvoFunctionsAs = function (eventName, eventSchema) {
|
|
87
|
+
var result = false;
|
|
88
|
+
if (this.lookForEventSchemaIn(eventName, eventSchema, this.avoFunctionsEventsParams)) {
|
|
89
|
+
result = true;
|
|
90
|
+
}
|
|
91
|
+
if (result) {
|
|
92
|
+
delete this.avoFunctionsEventsParams[eventName];
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
};
|
|
96
|
+
AvoDeduplicator.prototype.lookForEventSchemaIn = function (eventName, eventSchema, eventsStorage) {
|
|
97
|
+
for (var otherEventName in eventsStorage) {
|
|
98
|
+
if (eventsStorage.hasOwnProperty(otherEventName)) {
|
|
99
|
+
if (otherEventName === eventName) {
|
|
100
|
+
var otherSchema = AvoSchemaParser_1.AvoSchemaParser.extractSchema(eventsStorage[eventName]);
|
|
101
|
+
if (otherSchema && (0, utils_1.deepEquals)(eventSchema, otherSchema)) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
};
|
|
109
|
+
AvoDeduplicator.prototype.clearOldEvents = function () {
|
|
110
|
+
var now = Date.now();
|
|
111
|
+
var msToConsiderOld = 300;
|
|
112
|
+
for (var time in this.avoFunctionsEvents) {
|
|
113
|
+
if (this.avoFunctionsEvents.hasOwnProperty(time)) {
|
|
114
|
+
var timestamp = Number(time) || 0;
|
|
115
|
+
if (now - timestamp > msToConsiderOld) {
|
|
116
|
+
var eventName = this.avoFunctionsEvents[time];
|
|
117
|
+
delete this.avoFunctionsEvents[time];
|
|
118
|
+
delete this.avoFunctionsEventsParams[eventName];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (var time in this.manualEvents) {
|
|
123
|
+
if (this.manualEvents.hasOwnProperty(time)) {
|
|
124
|
+
var timestamp = Number(time) || 0;
|
|
125
|
+
if (now - timestamp > msToConsiderOld) {
|
|
126
|
+
var eventName = this.manualEvents[time];
|
|
127
|
+
delete this.manualEvents[time];
|
|
128
|
+
delete this.manualEventsParams[eventName];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
// used in tests
|
|
134
|
+
AvoDeduplicator.prototype._clearEvents = function () {
|
|
135
|
+
this.avoFunctionsEvents = {};
|
|
136
|
+
this.manualEvents = {};
|
|
137
|
+
this.avoFunctionsEventsParams = {};
|
|
138
|
+
this.manualEventsParams = {};
|
|
139
|
+
};
|
|
140
|
+
return AvoDeduplicator;
|
|
141
|
+
}());
|
|
142
|
+
exports.AvoDeduplicator = AvoDeduplicator;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var AvoGuid = /** @class */ (function () {
|
|
4
|
+
function AvoGuid() {
|
|
5
|
+
}
|
|
6
|
+
AvoGuid.newGuid = function () {
|
|
7
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
8
|
+
var r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
9
|
+
return v.toString(16);
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
return AvoGuid;
|
|
13
|
+
}());
|
|
14
|
+
exports.default = AvoGuid;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { AvoInspectorEnvValueType } from "./AvoInspectorEnv";
|
|
2
|
+
import { AvoSessionTracker } from "./AvoSessionTracker";
|
|
3
|
+
import { AvoBatcher } from "./AvoBatcher";
|
|
4
|
+
import { AvoStorage } from "./AvoStorage";
|
|
5
|
+
import { AvoDeduplicator } from "./AvoDeduplicator";
|
|
6
|
+
export declare class AvoInspector {
|
|
7
|
+
environment: AvoInspectorEnvValueType;
|
|
8
|
+
avoBatcher: AvoBatcher;
|
|
9
|
+
avoDeduplicator: AvoDeduplicator;
|
|
10
|
+
sessionTracker: AvoSessionTracker;
|
|
11
|
+
apiKey: string;
|
|
12
|
+
version: string;
|
|
13
|
+
static avoStorage: AvoStorage;
|
|
14
|
+
private static _batchSize;
|
|
15
|
+
static get batchSize(): number;
|
|
16
|
+
static set batchSize(newSize: number);
|
|
17
|
+
private static _batchFlushSeconds;
|
|
18
|
+
static get batchFlushSeconds(): number;
|
|
19
|
+
private static _shouldLog;
|
|
20
|
+
static get shouldLog(): boolean;
|
|
21
|
+
static set shouldLog(enable: boolean);
|
|
22
|
+
constructor(options: {
|
|
23
|
+
apiKey: string;
|
|
24
|
+
env: AvoInspectorEnvValueType;
|
|
25
|
+
version: string;
|
|
26
|
+
appName?: string;
|
|
27
|
+
});
|
|
28
|
+
trackSchemaFromEvent(eventName: string, eventProperties: {
|
|
29
|
+
[propName: string]: any;
|
|
30
|
+
}): Array<{
|
|
31
|
+
propertyName: string;
|
|
32
|
+
propertyType: string;
|
|
33
|
+
children?: any;
|
|
34
|
+
}>;
|
|
35
|
+
private _avoFunctionTrackSchemaFromEvent;
|
|
36
|
+
trackSchema(eventName: string, eventSchema: Array<{
|
|
37
|
+
propertyName: string;
|
|
38
|
+
propertyType: string;
|
|
39
|
+
children?: any;
|
|
40
|
+
}>): void;
|
|
41
|
+
private trackSchemaInternal;
|
|
42
|
+
enableLogging(enable: boolean): void;
|
|
43
|
+
extractSchema(eventProperties: {
|
|
44
|
+
[propName: string]: any;
|
|
45
|
+
}, shouldLogIfEnabled?: boolean): Array<{
|
|
46
|
+
propertyName: string;
|
|
47
|
+
propertyType: string;
|
|
48
|
+
children?: any;
|
|
49
|
+
}>;
|
|
50
|
+
setBatchSize(newBatchSize: number): void;
|
|
51
|
+
setBatchFlushSeconds(newBatchFlushSeconds: number): void;
|
|
52
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AvoInspector = void 0;
|
|
4
|
+
var AvoInspectorEnv_1 = require("./AvoInspectorEnv");
|
|
5
|
+
var AvoSchemaParser_1 = require("./AvoSchemaParser");
|
|
6
|
+
var AvoSessionTracker_1 = require("./AvoSessionTracker");
|
|
7
|
+
var AvoBatcher_1 = require("./AvoBatcher");
|
|
8
|
+
var AvoNetworkCallsHandler_1 = require("./AvoNetworkCallsHandler");
|
|
9
|
+
var AvoStorage_1 = require("./AvoStorage");
|
|
10
|
+
var AvoDeduplicator_1 = require("./AvoDeduplicator");
|
|
11
|
+
var utils_1 = require("./utils");
|
|
12
|
+
var libVersion = require("../package.json").version;
|
|
13
|
+
var AvoInspector = /** @class */ (function () {
|
|
14
|
+
// constructor(apiKey: string, env: AvoInspectorEnv, version: string) {
|
|
15
|
+
function AvoInspector(options) {
|
|
16
|
+
var _this = this;
|
|
17
|
+
// the constructor does aggressive null/undefined checking because same code paths will be accessible from JS
|
|
18
|
+
if ((0, utils_1.isValueEmpty)(options.env)) {
|
|
19
|
+
this.environment = AvoInspectorEnv_1.AvoInspectorEnv.Dev;
|
|
20
|
+
console.warn("[Avo Inspector] No environment provided. Defaulting to dev.");
|
|
21
|
+
}
|
|
22
|
+
else if (Object.values(AvoInspectorEnv_1.AvoInspectorEnv).indexOf(options.env) === -1) {
|
|
23
|
+
this.environment = AvoInspectorEnv_1.AvoInspectorEnv.Dev;
|
|
24
|
+
console.warn("[Avo Inspector] Unsupported environment provided. Defaulting to dev. Supported environments - Dev, Staging, Prod.");
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
this.environment = options.env;
|
|
28
|
+
}
|
|
29
|
+
if ((0, utils_1.isValueEmpty)(options.apiKey)) {
|
|
30
|
+
throw new Error("[Avo Inspector] No API key provided. Inspector can't operate without API key.");
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
this.apiKey = options.apiKey;
|
|
34
|
+
}
|
|
35
|
+
if ((0, utils_1.isValueEmpty)(options.version)) {
|
|
36
|
+
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.");
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.version = options.version;
|
|
40
|
+
}
|
|
41
|
+
if (this.environment === AvoInspectorEnv_1.AvoInspectorEnv.Dev) {
|
|
42
|
+
AvoInspector._batchSize = 1;
|
|
43
|
+
AvoInspector._shouldLog = true;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
AvoInspector._batchSize = 30;
|
|
47
|
+
AvoInspector._batchFlushSeconds = 30;
|
|
48
|
+
AvoInspector._shouldLog = false;
|
|
49
|
+
}
|
|
50
|
+
AvoInspector.avoStorage = new AvoStorage_1.AvoStorage(AvoInspector._shouldLog);
|
|
51
|
+
var avoNetworkCallsHandler = new AvoNetworkCallsHandler_1.AvoNetworkCallsHandler(this.apiKey, this.environment.toString(), options.appName || "", this.version, libVersion);
|
|
52
|
+
this.avoBatcher = new AvoBatcher_1.AvoBatcher(avoNetworkCallsHandler);
|
|
53
|
+
this.sessionTracker = new AvoSessionTracker_1.AvoSessionTracker(this.avoBatcher);
|
|
54
|
+
this.avoDeduplicator = new AvoDeduplicator_1.AvoDeduplicator();
|
|
55
|
+
try {
|
|
56
|
+
if (process.env.BROWSER) {
|
|
57
|
+
// XXX make node/browser split clearer
|
|
58
|
+
if (typeof window !== "undefined") {
|
|
59
|
+
window.addEventListener("load", function () {
|
|
60
|
+
_this.sessionTracker.startOrProlongSession(Date.now());
|
|
61
|
+
}, false);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
this.sessionTracker.startOrProlongSession(Date.now());
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
Object.defineProperty(AvoInspector, "batchSize", {
|
|
73
|
+
get: function () {
|
|
74
|
+
return this._batchSize;
|
|
75
|
+
},
|
|
76
|
+
set: function (newSize) {
|
|
77
|
+
if (newSize < 1) {
|
|
78
|
+
this._batchSize = 1;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this._batchSize = newSize;
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
enumerable: false,
|
|
85
|
+
configurable: true
|
|
86
|
+
});
|
|
87
|
+
Object.defineProperty(AvoInspector, "batchFlushSeconds", {
|
|
88
|
+
get: function () {
|
|
89
|
+
return this._batchFlushSeconds;
|
|
90
|
+
},
|
|
91
|
+
enumerable: false,
|
|
92
|
+
configurable: true
|
|
93
|
+
});
|
|
94
|
+
Object.defineProperty(AvoInspector, "shouldLog", {
|
|
95
|
+
get: function () {
|
|
96
|
+
return this._shouldLog;
|
|
97
|
+
},
|
|
98
|
+
set: function (enable) {
|
|
99
|
+
this._shouldLog = enable;
|
|
100
|
+
},
|
|
101
|
+
enumerable: false,
|
|
102
|
+
configurable: true
|
|
103
|
+
});
|
|
104
|
+
AvoInspector.prototype.trackSchemaFromEvent = function (eventName, eventProperties) {
|
|
105
|
+
try {
|
|
106
|
+
if (this.avoDeduplicator.shouldRegisterEvent(eventName, eventProperties, false)) {
|
|
107
|
+
if (AvoInspector.shouldLog) {
|
|
108
|
+
console.log("Avo Inspector: supplied event " +
|
|
109
|
+
eventName +
|
|
110
|
+
" with params " +
|
|
111
|
+
JSON.stringify(eventProperties));
|
|
112
|
+
}
|
|
113
|
+
var eventSchema = this.extractSchema(eventProperties, false);
|
|
114
|
+
this.trackSchemaInternal(eventName, eventSchema, null, null);
|
|
115
|
+
return eventSchema;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
if (AvoInspector.shouldLog) {
|
|
119
|
+
console.log("Avo Inspector: Deduplicated event: " + eventName);
|
|
120
|
+
}
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
AvoInspector.prototype._avoFunctionTrackSchemaFromEvent = function (eventName, eventProperties, eventId, eventHash) {
|
|
130
|
+
try {
|
|
131
|
+
if (this.avoDeduplicator.shouldRegisterEvent(eventName, eventProperties, true)) {
|
|
132
|
+
if (AvoInspector.shouldLog) {
|
|
133
|
+
console.log("Avo Inspector: supplied event " +
|
|
134
|
+
eventName +
|
|
135
|
+
" with params " +
|
|
136
|
+
JSON.stringify(eventProperties));
|
|
137
|
+
}
|
|
138
|
+
var eventSchema = this.extractSchema(eventProperties, false);
|
|
139
|
+
this.trackSchemaInternal(eventName, eventSchema, eventId, eventHash);
|
|
140
|
+
return eventSchema;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
if (AvoInspector.shouldLog) {
|
|
144
|
+
console.log("Avo Inspector: Deduplicated event: " + eventName);
|
|
145
|
+
}
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
AvoInspector.prototype.trackSchema = function (eventName, eventSchema) {
|
|
155
|
+
try {
|
|
156
|
+
if (this.avoDeduplicator.shouldRegisterSchemaFromManually(eventName, eventSchema)) {
|
|
157
|
+
if (AvoInspector.shouldLog) {
|
|
158
|
+
console.log("Avo Inspector: supplied event " +
|
|
159
|
+
eventName +
|
|
160
|
+
" with schema " +
|
|
161
|
+
JSON.stringify(eventSchema));
|
|
162
|
+
}
|
|
163
|
+
this.trackSchemaInternal(eventName, eventSchema, null, null);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
if (AvoInspector.shouldLog) {
|
|
167
|
+
console.log("Avo Inspector: Deduplicated event: " + eventName);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch (e) {
|
|
172
|
+
console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
AvoInspector.prototype.trackSchemaInternal = function (eventName, eventSchema, eventId, eventHash) {
|
|
176
|
+
try {
|
|
177
|
+
this.sessionTracker.startOrProlongSession(Date.now());
|
|
178
|
+
this.avoBatcher.handleTrackSchema(eventName, eventSchema, eventId, eventHash);
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
AvoInspector.prototype.enableLogging = function (enable) {
|
|
185
|
+
AvoInspector._shouldLog = enable;
|
|
186
|
+
};
|
|
187
|
+
AvoInspector.prototype.extractSchema = function (eventProperties, shouldLogIfEnabled) {
|
|
188
|
+
if (shouldLogIfEnabled === void 0) { shouldLogIfEnabled = true; }
|
|
189
|
+
try {
|
|
190
|
+
this.sessionTracker.startOrProlongSession(Date.now());
|
|
191
|
+
if (this.avoDeduplicator.hasSeenEventParams(eventProperties, true)) {
|
|
192
|
+
if (shouldLogIfEnabled && AvoInspector.shouldLog) {
|
|
193
|
+
console.warn("Avo Inspector: WARNING! You are trying to extract schema shape that was just reported by your Avo functions. " +
|
|
194
|
+
"This is an indicator of duplicate inspector reporting. " +
|
|
195
|
+
"Please reach out to support@avo.app for advice if you are not sure how to handle this.");
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (AvoInspector.shouldLog) {
|
|
199
|
+
console.log("Avo Inspector: extracting schema from " +
|
|
200
|
+
JSON.stringify(eventProperties));
|
|
201
|
+
}
|
|
202
|
+
return AvoSchemaParser_1.AvoSchemaParser.extractSchema(eventProperties);
|
|
203
|
+
}
|
|
204
|
+
catch (e) {
|
|
205
|
+
console.error("Avo Inspector: something went wrong. Please report to support@avo.app.", e);
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
AvoInspector.prototype.setBatchSize = function (newBatchSize) {
|
|
210
|
+
AvoInspector._batchSize = newBatchSize;
|
|
211
|
+
};
|
|
212
|
+
AvoInspector.prototype.setBatchFlushSeconds = function (newBatchFlushSeconds) {
|
|
213
|
+
AvoInspector._batchFlushSeconds = newBatchFlushSeconds;
|
|
214
|
+
};
|
|
215
|
+
AvoInspector._batchSize = 30;
|
|
216
|
+
AvoInspector._batchFlushSeconds = 30;
|
|
217
|
+
AvoInspector._shouldLog = false;
|
|
218
|
+
return AvoInspector;
|
|
219
|
+
}());
|
|
220
|
+
exports.AvoInspector = AvoInspector;
|