@tracelog/lib 0.4.0 → 0.5.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/dist/browser/tracelog.js +620 -658
- package/dist/cjs/api.d.ts +1 -53
- package/dist/cjs/api.js +0 -59
- package/dist/cjs/app.constants.d.ts +1 -1
- package/dist/cjs/app.d.ts +1 -5
- package/dist/cjs/app.js +4 -12
- package/dist/cjs/constants/api.constants.d.ts +5 -2
- package/dist/cjs/constants/api.constants.js +5 -14
- package/dist/cjs/constants/config.constants.d.ts +3 -3
- package/dist/cjs/constants/config.constants.js +3 -3
- package/dist/cjs/constants/error.constants.d.ts +7 -2
- package/dist/cjs/constants/error.constants.js +13 -2
- package/dist/cjs/handlers/click.handler.js +0 -6
- package/dist/cjs/handlers/error.handler.js +9 -0
- package/dist/cjs/handlers/scroll.handler.js +0 -5
- package/dist/cjs/handlers/session.handler.js +5 -2
- package/dist/cjs/integrations/google-analytics.integration.d.ts +1 -1
- package/dist/cjs/integrations/google-analytics.integration.js +2 -1
- package/dist/cjs/managers/api.manager.d.ts +1 -1
- package/dist/cjs/managers/api.manager.js +3 -3
- package/dist/cjs/managers/config.builder.d.ts +33 -0
- package/dist/cjs/managers/config.builder.js +116 -0
- package/dist/cjs/managers/config.manager.d.ts +13 -14
- package/dist/cjs/managers/config.manager.js +52 -58
- package/dist/cjs/managers/event.manager.d.ts +1 -46
- package/dist/cjs/managers/event.manager.js +15 -70
- package/dist/cjs/managers/sender.manager.d.ts +1 -28
- package/dist/cjs/managers/sender.manager.js +43 -73
- package/dist/cjs/managers/session.manager.d.ts +2 -49
- package/dist/cjs/managers/session.manager.js +42 -83
- package/dist/cjs/managers/state.manager.d.ts +1 -28
- package/dist/cjs/managers/state.manager.js +5 -33
- package/dist/cjs/managers/storage.manager.d.ts +6 -0
- package/dist/cjs/managers/storage.manager.js +18 -1
- package/dist/cjs/public-api.d.ts +1 -1
- package/dist/cjs/test-bridge.d.ts +3 -2
- package/dist/cjs/test-bridge.js +34 -7
- package/dist/cjs/types/api.types.d.ts +24 -8
- package/dist/cjs/types/api.types.js +24 -8
- package/dist/cjs/types/event.types.d.ts +2 -4
- package/dist/cjs/types/event.types.js +0 -1
- package/dist/cjs/types/test-bridge.types.d.ts +2 -1
- package/dist/cjs/utils/logging/debug-logger.utils.d.ts +1 -2
- package/dist/cjs/utils/logging/debug-logger.utils.js +2 -3
- package/dist/cjs/utils/validations/config-validations.utils.d.ts +1 -26
- package/dist/cjs/utils/validations/config-validations.utils.js +5 -117
- package/dist/cjs/utils/validations/event-validations.utils.d.ts +2 -2
- package/dist/cjs/utils/validations/metadata-validations.utils.d.ts +3 -3
- package/dist/cjs/utils/validations/metadata-validations.utils.js +41 -3
- package/dist/esm/api.d.ts +1 -53
- package/dist/esm/api.js +0 -59
- package/dist/esm/app.constants.d.ts +1 -1
- package/dist/esm/app.d.ts +1 -5
- package/dist/esm/app.js +5 -13
- package/dist/esm/constants/api.constants.d.ts +5 -2
- package/dist/esm/constants/api.constants.js +5 -13
- package/dist/esm/constants/config.constants.d.ts +3 -3
- package/dist/esm/constants/config.constants.js +3 -3
- package/dist/esm/constants/error.constants.d.ts +7 -2
- package/dist/esm/constants/error.constants.js +12 -1
- package/dist/esm/handlers/click.handler.js +0 -6
- package/dist/esm/handlers/error.handler.js +10 -1
- package/dist/esm/handlers/scroll.handler.js +0 -5
- package/dist/esm/handlers/session.handler.js +5 -2
- package/dist/esm/integrations/google-analytics.integration.d.ts +1 -1
- package/dist/esm/integrations/google-analytics.integration.js +2 -1
- package/dist/esm/managers/api.manager.d.ts +1 -1
- package/dist/esm/managers/api.manager.js +3 -3
- package/dist/esm/managers/config.builder.d.ts +33 -0
- package/dist/esm/managers/config.builder.js +112 -0
- package/dist/esm/managers/config.manager.d.ts +13 -14
- package/dist/esm/managers/config.manager.js +54 -60
- package/dist/esm/managers/event.manager.d.ts +1 -46
- package/dist/esm/managers/event.manager.js +15 -70
- package/dist/esm/managers/sender.manager.d.ts +1 -28
- package/dist/esm/managers/sender.manager.js +44 -74
- package/dist/esm/managers/session.manager.d.ts +2 -49
- package/dist/esm/managers/session.manager.js +42 -83
- package/dist/esm/managers/state.manager.d.ts +1 -28
- package/dist/esm/managers/state.manager.js +4 -33
- package/dist/esm/managers/storage.manager.d.ts +6 -0
- package/dist/esm/managers/storage.manager.js +18 -1
- package/dist/esm/public-api.d.ts +1 -1
- package/dist/esm/test-bridge.d.ts +3 -2
- package/dist/esm/test-bridge.js +34 -7
- package/dist/esm/types/api.types.d.ts +24 -8
- package/dist/esm/types/api.types.js +24 -8
- package/dist/esm/types/event.types.d.ts +2 -4
- package/dist/esm/types/event.types.js +0 -1
- package/dist/esm/types/test-bridge.types.d.ts +2 -1
- package/dist/esm/utils/logging/debug-logger.utils.d.ts +1 -2
- package/dist/esm/utils/logging/debug-logger.utils.js +3 -4
- package/dist/esm/utils/validations/config-validations.utils.d.ts +1 -26
- package/dist/esm/utils/validations/config-validations.utils.js +5 -114
- package/dist/esm/utils/validations/event-validations.utils.d.ts +2 -2
- package/dist/esm/utils/validations/metadata-validations.utils.d.ts +3 -3
- package/dist/esm/utils/validations/metadata-validations.utils.js +41 -3
- package/package.json +1 -1
|
@@ -17,8 +17,7 @@ export declare enum ScrollDirection {
|
|
|
17
17
|
}
|
|
18
18
|
export declare enum ErrorType {
|
|
19
19
|
JS_ERROR = "js_error",
|
|
20
|
-
PROMISE_REJECTION = "promise_rejection"
|
|
21
|
-
NETWORK_ERROR = "network_error"
|
|
20
|
+
PROMISE_REJECTION = "promise_rejection"
|
|
22
21
|
}
|
|
23
22
|
export interface ScrollData {
|
|
24
23
|
depth: number;
|
|
@@ -48,7 +47,7 @@ export interface ClickTrackingElementData {
|
|
|
48
47
|
}
|
|
49
48
|
export interface CustomEventData {
|
|
50
49
|
name: string;
|
|
51
|
-
metadata?: Record<string, MetadataType
|
|
50
|
+
metadata?: Record<string, MetadataType> | Record<string, MetadataType>[];
|
|
52
51
|
}
|
|
53
52
|
export interface WebVitalsData {
|
|
54
53
|
type: WebVitalType;
|
|
@@ -94,7 +93,6 @@ export interface EventData {
|
|
|
94
93
|
custom_event?: CustomEventData;
|
|
95
94
|
web_vitals?: WebVitalsData;
|
|
96
95
|
page_view?: PageViewData;
|
|
97
|
-
session_start_recovered?: boolean;
|
|
98
96
|
session_end_reason?: SessionEndReason;
|
|
99
97
|
error_data?: ErrorData;
|
|
100
98
|
utm?: UTM;
|
|
@@ -18,13 +18,14 @@ export interface TraceLogTestBridge {
|
|
|
18
18
|
init(config: AppConfig): Promise<void>;
|
|
19
19
|
destroy(): Promise<void>;
|
|
20
20
|
isInitializing(): boolean;
|
|
21
|
-
sendCustomEvent(name: string, data?: Record<string, unknown>): void;
|
|
21
|
+
sendCustomEvent(name: string, data?: Record<string, unknown> | Record<string, unknown>[]): void;
|
|
22
22
|
on(event: string, callback: (data: any) => void): void;
|
|
23
23
|
off(event: string, callback: (data: any) => void): void;
|
|
24
24
|
getSessionData(): Record<string, unknown> | null;
|
|
25
25
|
setSessionTimeout(timeout: number): void;
|
|
26
26
|
getQueueLength(): number;
|
|
27
27
|
forceInitLock(enabled?: boolean): void;
|
|
28
|
+
simulatePersistedEvents(events: any[]): void;
|
|
28
29
|
get<T extends keyof State>(key: T): State[T];
|
|
29
30
|
getStorageManager(): TraceLogStorageManager | null;
|
|
30
31
|
getEventManager(): EventManager | null;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
declare class DebugLogger extends StateManager {
|
|
1
|
+
declare class DebugLogger {
|
|
3
2
|
clientError: (ns: string, msg: string, data?: unknown) => void;
|
|
4
3
|
clientWarn: (ns: string, msg: string, data?: unknown) => void;
|
|
5
4
|
info: (ns: string, msg: string, data?: unknown) => void;
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.debugLog = void 0;
|
|
4
4
|
const state_manager_1 = require("../../managers/state.manager");
|
|
5
|
-
class DebugLogger
|
|
5
|
+
class DebugLogger {
|
|
6
6
|
constructor() {
|
|
7
|
-
super(...arguments);
|
|
8
7
|
this.clientError = (ns, msg, data) => this.log('CLIENT_ERROR', ns, msg, data);
|
|
9
8
|
this.clientWarn = (ns, msg, data) => this.log('CLIENT_WARN', ns, msg, data);
|
|
10
9
|
this.info = (ns, msg, data) => this.log('INFO', ns, msg, data);
|
|
@@ -14,7 +13,7 @@ class DebugLogger extends state_manager_1.StateManager {
|
|
|
14
13
|
this.verbose = (ns, msg, data) => this.log('VERBOSE', ns, msg, data);
|
|
15
14
|
}
|
|
16
15
|
log(level, ns, msg, data) {
|
|
17
|
-
const mode =
|
|
16
|
+
const mode = (0, state_manager_1.getGlobalState)()?.config?.mode;
|
|
18
17
|
if (!this.shouldShow(level, mode))
|
|
19
18
|
return;
|
|
20
19
|
const formattedMsg = `[TraceLog:${ns}] ${msg}`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppConfig,
|
|
1
|
+
import { AppConfig, ApiConfig } from '../../types';
|
|
2
2
|
/**
|
|
3
3
|
* Validates the app configuration object (before normalization)
|
|
4
4
|
* This validates the structure and basic types but allows for normalization afterward
|
|
@@ -16,31 +16,6 @@ export declare const validateAppConfig: (config: AppConfig) => void;
|
|
|
16
16
|
* @throws {AppConfigValidationError} If other configuration validation fails
|
|
17
17
|
*/
|
|
18
18
|
export declare const validateAndNormalizeConfig: (config: AppConfig) => AppConfig;
|
|
19
|
-
/**
|
|
20
|
-
* Validates a complete configuration object
|
|
21
|
-
* @param config - The configuration to validate
|
|
22
|
-
* @returns Validation result with errors and warnings
|
|
23
|
-
*/
|
|
24
|
-
export declare const validateConfig: (config: Config) => {
|
|
25
|
-
errors: string[];
|
|
26
|
-
warnings: string[];
|
|
27
|
-
samplingRate: number;
|
|
28
|
-
};
|
|
29
|
-
export declare const normalizeConfig: (config: Config) => {
|
|
30
|
-
config: Config;
|
|
31
|
-
errors: string[];
|
|
32
|
-
warnings: string[];
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* Validates the final configuration
|
|
36
|
-
* @param config - The configuration to validate
|
|
37
|
-
* @returns Validation result with errors and warnings
|
|
38
|
-
*/
|
|
39
|
-
export declare const validateFinalConfig: (config: Config) => {
|
|
40
|
-
errors: string[];
|
|
41
|
-
warnings: string[];
|
|
42
|
-
samplingRate: number;
|
|
43
|
-
};
|
|
44
19
|
/**
|
|
45
20
|
* Type guard to check if a JSON response is a valid API config
|
|
46
21
|
* @param json - The JSON to validate
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isValidConfigApiResponse = exports.
|
|
3
|
+
exports.isValidConfigApiResponse = exports.validateAndNormalizeConfig = exports.validateAppConfig = void 0;
|
|
4
4
|
const constants_1 = require("../../constants");
|
|
5
5
|
const types_1 = require("../../types");
|
|
6
6
|
const validation_error_types_1 = require("../../types/validation-error.types");
|
|
@@ -209,121 +209,6 @@ const validateAndNormalizeConfig = (config) => {
|
|
|
209
209
|
return normalizedConfig;
|
|
210
210
|
};
|
|
211
211
|
exports.validateAndNormalizeConfig = validateAndNormalizeConfig;
|
|
212
|
-
/**
|
|
213
|
-
* Validates sampling rate
|
|
214
|
-
* @param samplingRate - The sampling rate to validate
|
|
215
|
-
* @param errors - Array to push errors to
|
|
216
|
-
*/
|
|
217
|
-
const validateSamplingRate = (samplingRate, errors) => {
|
|
218
|
-
if (samplingRate === undefined) {
|
|
219
|
-
return undefined;
|
|
220
|
-
}
|
|
221
|
-
if (typeof samplingRate !== 'number') {
|
|
222
|
-
errors.push('samplingRate must be a number');
|
|
223
|
-
return constants_1.DEFAULT_SAMPLING_RATE;
|
|
224
|
-
}
|
|
225
|
-
if (Number.isNaN(samplingRate) || samplingRate <= 0 || samplingRate > 1) {
|
|
226
|
-
errors.push(constants_1.VALIDATION_MESSAGES.INVALID_SAMPLING_RATE);
|
|
227
|
-
return constants_1.DEFAULT_SAMPLING_RATE;
|
|
228
|
-
}
|
|
229
|
-
return samplingRate;
|
|
230
|
-
};
|
|
231
|
-
/**
|
|
232
|
-
* Validates excluded URL paths
|
|
233
|
-
* @param excludedUrlPaths - The excluded URL paths to validate
|
|
234
|
-
* @param errors - Array to push errors to
|
|
235
|
-
* @param prefix - Optional prefix for error messages
|
|
236
|
-
*/
|
|
237
|
-
const validateExcludedUrlPaths = (excludedUrlPaths, errors, prefix = '') => {
|
|
238
|
-
if (excludedUrlPaths !== undefined) {
|
|
239
|
-
if (Array.isArray(excludedUrlPaths)) {
|
|
240
|
-
for (const [index, path] of excludedUrlPaths.entries()) {
|
|
241
|
-
if (typeof path === 'string') {
|
|
242
|
-
try {
|
|
243
|
-
new RegExp(path);
|
|
244
|
-
}
|
|
245
|
-
catch {
|
|
246
|
-
errors.push(`${prefix}excludedUrlPaths[${index}] is not a valid regex pattern`);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
errors.push(`${prefix}excludedUrlPaths[${index}] must be a string`);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
errors.push(`${prefix}excludedUrlPaths must be an array`);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
/**
|
|
260
|
-
* Validates a complete configuration object
|
|
261
|
-
* @param config - The configuration to validate
|
|
262
|
-
* @returns Validation result with errors and warnings
|
|
263
|
-
*/
|
|
264
|
-
const validateConfig = (config) => {
|
|
265
|
-
const errors = [];
|
|
266
|
-
const warnings = [];
|
|
267
|
-
if (config.sessionTimeout !== undefined) {
|
|
268
|
-
if (typeof config.sessionTimeout !== 'number') {
|
|
269
|
-
errors.push('sessionTimeout must be a number');
|
|
270
|
-
}
|
|
271
|
-
else if (config.sessionTimeout < constants_1.MIN_SESSION_TIMEOUT_MS) {
|
|
272
|
-
errors.push('sessionTimeout must be at least 30 seconds (30000ms)');
|
|
273
|
-
}
|
|
274
|
-
else if (config.sessionTimeout > constants_1.MAX_SESSION_TIMEOUT_MS) {
|
|
275
|
-
warnings.push('sessionTimeout is very long (>24 hours), consider reducing it');
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
if (config.globalMetadata !== undefined) {
|
|
279
|
-
if (typeof config.globalMetadata !== 'object' || config.globalMetadata === null) {
|
|
280
|
-
errors.push('globalMetadata must be an object');
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
const metadataSize = JSON.stringify(config.globalMetadata).length;
|
|
284
|
-
if (metadataSize > 10240) {
|
|
285
|
-
errors.push('globalMetadata is too large (max 10KB)');
|
|
286
|
-
}
|
|
287
|
-
if (Object.keys(config.globalMetadata).length > 12) {
|
|
288
|
-
errors.push('globalMetadata has too many keys (max 12)');
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
// No custom API endpoints supported
|
|
293
|
-
const validatedSamplingRate = validateSamplingRate(config.samplingRate, errors) ?? constants_1.DEFAULT_SAMPLING_RATE;
|
|
294
|
-
if (config.tags !== undefined && !Array.isArray(config.tags)) {
|
|
295
|
-
errors.push('tags must be an array');
|
|
296
|
-
}
|
|
297
|
-
validateExcludedUrlPaths(config.excludedUrlPaths, errors);
|
|
298
|
-
return { errors, warnings, samplingRate: validatedSamplingRate };
|
|
299
|
-
};
|
|
300
|
-
exports.validateConfig = validateConfig;
|
|
301
|
-
const normalizeConfig = (config) => {
|
|
302
|
-
const { errors, warnings, samplingRate } = (0, exports.validateConfig)(config);
|
|
303
|
-
return {
|
|
304
|
-
config: {
|
|
305
|
-
...config,
|
|
306
|
-
samplingRate,
|
|
307
|
-
},
|
|
308
|
-
errors,
|
|
309
|
-
warnings,
|
|
310
|
-
};
|
|
311
|
-
};
|
|
312
|
-
exports.normalizeConfig = normalizeConfig;
|
|
313
|
-
/**
|
|
314
|
-
* Validates the final configuration
|
|
315
|
-
* @param config - The configuration to validate
|
|
316
|
-
* @returns Validation result with errors and warnings
|
|
317
|
-
*/
|
|
318
|
-
const validateFinalConfig = (config) => {
|
|
319
|
-
const errors = [];
|
|
320
|
-
const warnings = [];
|
|
321
|
-
const validatedSamplingRate = validateSamplingRate(config.samplingRate, errors) ?? constants_1.DEFAULT_SAMPLING_RATE;
|
|
322
|
-
validateExcludedUrlPaths(config.excludedUrlPaths, errors);
|
|
323
|
-
// No custom API endpoints supported
|
|
324
|
-
return { errors, warnings, samplingRate: validatedSamplingRate };
|
|
325
|
-
};
|
|
326
|
-
exports.validateFinalConfig = validateFinalConfig;
|
|
327
212
|
/**
|
|
328
213
|
* Type guard to check if a JSON response is a valid API config
|
|
329
214
|
* @param json - The JSON to validate
|
|
@@ -337,8 +222,11 @@ const isValidConfigApiResponse = (json) => {
|
|
|
337
222
|
const response = json;
|
|
338
223
|
const result = {
|
|
339
224
|
mode: response['mode'] === undefined || [types_1.Mode.QA, types_1.Mode.DEBUG].includes(response['mode']),
|
|
225
|
+
// Zero is valid for samplingRate (means "sample nothing")
|
|
340
226
|
samplingRate: response['samplingRate'] === undefined ||
|
|
341
|
-
(typeof response['samplingRate'] === 'number' &&
|
|
227
|
+
(typeof response['samplingRate'] === 'number' &&
|
|
228
|
+
response['samplingRate'] >= 0 &&
|
|
229
|
+
response['samplingRate'] <= 1),
|
|
342
230
|
tags: response['tags'] === undefined || Array.isArray(response['tags']),
|
|
343
231
|
excludedUrlPaths: response['excludedUrlPaths'] === undefined || Array.isArray(response['excludedUrlPaths']),
|
|
344
232
|
ipExcluded: response['ipExcluded'] === undefined || typeof response['ipExcluded'] === 'boolean',
|
|
@@ -5,8 +5,8 @@ import { MetadataType } from '../../types';
|
|
|
5
5
|
* @param metadata - Optional metadata to validate
|
|
6
6
|
* @returns Validation result with sanitized metadata if valid
|
|
7
7
|
*/
|
|
8
|
-
export declare const isEventValid: (eventName: string, metadata?: Record<string, unknown>) => {
|
|
8
|
+
export declare const isEventValid: (eventName: string, metadata?: Record<string, unknown> | Record<string, unknown>[]) => {
|
|
9
9
|
valid: boolean;
|
|
10
10
|
error?: string;
|
|
11
|
-
sanitizedMetadata?: Record<string, MetadataType
|
|
11
|
+
sanitizedMetadata?: Record<string, MetadataType> | Record<string, MetadataType>[];
|
|
12
12
|
};
|
|
@@ -9,14 +9,14 @@ export declare const isValidEventName: (eventName: string) => {
|
|
|
9
9
|
error?: string;
|
|
10
10
|
};
|
|
11
11
|
/**
|
|
12
|
-
* Validates metadata for events
|
|
12
|
+
* Validates metadata for events (supports both objects and arrays of objects)
|
|
13
13
|
* @param eventName - The event name (for error messages)
|
|
14
14
|
* @param metadata - The metadata to validate
|
|
15
15
|
* @param type - Type of metadata (globalMetadata or customEvent)
|
|
16
16
|
* @returns Validation result with sanitized metadata if valid
|
|
17
17
|
*/
|
|
18
|
-
export declare const isValidMetadata: (eventName: string, metadata: Record<string, unknown
|
|
18
|
+
export declare const isValidMetadata: (eventName: string, metadata: Record<string, unknown> | Record<string, unknown>[], type?: "globalMetadata" | "customEvent") => {
|
|
19
19
|
valid: boolean;
|
|
20
20
|
error?: string;
|
|
21
|
-
sanitizedMetadata?: Record<string, MetadataType
|
|
21
|
+
sanitizedMetadata?: Record<string, MetadataType> | Record<string, MetadataType>[];
|
|
22
22
|
};
|
|
@@ -45,13 +45,13 @@ const isValidEventName = (eventName) => {
|
|
|
45
45
|
};
|
|
46
46
|
exports.isValidEventName = isValidEventName;
|
|
47
47
|
/**
|
|
48
|
-
* Validates metadata
|
|
48
|
+
* Validates a single metadata object
|
|
49
49
|
* @param eventName - The event name (for error messages)
|
|
50
|
-
* @param metadata - The metadata to validate
|
|
50
|
+
* @param metadata - The metadata object to validate
|
|
51
51
|
* @param type - Type of metadata (globalMetadata or customEvent)
|
|
52
52
|
* @returns Validation result with sanitized metadata if valid
|
|
53
53
|
*/
|
|
54
|
-
const
|
|
54
|
+
const validateSingleMetadata = (eventName, metadata, type) => {
|
|
55
55
|
const sanitizedMetadata = (0, sanitize_utils_1.sanitizeMetadata)(metadata);
|
|
56
56
|
const intro = type && type === 'customEvent' ? `${type} "${eventName}" metadata error` : `${eventName} metadata error`;
|
|
57
57
|
if (!(0, type_guards_utils_1.isOnlyPrimitiveFields)(sanitizedMetadata)) {
|
|
@@ -112,4 +112,42 @@ const isValidMetadata = (eventName, metadata, type) => {
|
|
|
112
112
|
sanitizedMetadata,
|
|
113
113
|
};
|
|
114
114
|
};
|
|
115
|
+
/**
|
|
116
|
+
* Validates metadata for events (supports both objects and arrays of objects)
|
|
117
|
+
* @param eventName - The event name (for error messages)
|
|
118
|
+
* @param metadata - The metadata to validate
|
|
119
|
+
* @param type - Type of metadata (globalMetadata or customEvent)
|
|
120
|
+
* @returns Validation result with sanitized metadata if valid
|
|
121
|
+
*/
|
|
122
|
+
const isValidMetadata = (eventName, metadata, type) => {
|
|
123
|
+
if (Array.isArray(metadata)) {
|
|
124
|
+
const sanitizedArray = [];
|
|
125
|
+
const intro = type && type === 'customEvent' ? `${type} "${eventName}" metadata error` : `${eventName} metadata error`;
|
|
126
|
+
for (let i = 0; i < metadata.length; i++) {
|
|
127
|
+
const item = metadata[i];
|
|
128
|
+
if (typeof item !== 'object' || item === null || Array.isArray(item)) {
|
|
129
|
+
return {
|
|
130
|
+
valid: false,
|
|
131
|
+
error: `${intro}: array item at index ${i} must be an object.`,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const itemValidation = validateSingleMetadata(eventName, item, type);
|
|
135
|
+
if (!itemValidation.valid) {
|
|
136
|
+
return {
|
|
137
|
+
valid: false,
|
|
138
|
+
error: `${intro}: array item at index ${i} is invalid: ${itemValidation.error}`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
if (itemValidation.sanitizedMetadata) {
|
|
142
|
+
sanitizedArray.push(itemValidation.sanitizedMetadata);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Allow empty arrays after sanitization
|
|
146
|
+
return {
|
|
147
|
+
valid: true,
|
|
148
|
+
sanitizedMetadata: sanitizedArray,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return validateSingleMetadata(eventName, metadata, type);
|
|
152
|
+
};
|
|
115
153
|
exports.isValidMetadata = isValidMetadata;
|
package/dist/esm/api.d.ts
CHANGED
|
@@ -1,60 +1,8 @@
|
|
|
1
1
|
import { MetadataType, AppConfig, EmitterCallback, EmitterMap } from './types';
|
|
2
2
|
import './types/window.types';
|
|
3
|
-
/**
|
|
4
|
-
* Initializes the tracelog app with the provided configuration.
|
|
5
|
-
* If already initialized, this function returns early without error.
|
|
6
|
-
* @param appConfig - The configuration object for the app
|
|
7
|
-
* @throws {Error} If initialization fails or environment is invalid
|
|
8
|
-
* @example
|
|
9
|
-
* await tracelog.init({ id: 'my-project-id' });
|
|
10
|
-
*/
|
|
11
3
|
export declare const init: (appConfig: AppConfig) => Promise<void>;
|
|
12
|
-
|
|
13
|
-
* Sends a custom event with the specified name and metadata.
|
|
14
|
-
* @param name - The name of the custom event.
|
|
15
|
-
* @param metadata - Optional metadata to attach to the event.
|
|
16
|
-
* @example
|
|
17
|
-
* // Send a custom event with metadata
|
|
18
|
-
* tracelog.event('user_signup', { method: 'email', plan: 'premium' });
|
|
19
|
-
* @example
|
|
20
|
-
* // Send a custom event without metadata
|
|
21
|
-
* tracelog.event('user_login');
|
|
22
|
-
* @remarks
|
|
23
|
-
* This function should be called after the app has been initialized using the `tracelog.init` function.
|
|
24
|
-
*/
|
|
25
|
-
export declare const event: (name: string, metadata?: Record<string, MetadataType>) => void;
|
|
26
|
-
/**
|
|
27
|
-
* Subscribe to events emitted by TraceLog
|
|
28
|
-
* @param event - Event name to listen to
|
|
29
|
-
* @param callback - Function to call when event is emitted
|
|
30
|
-
* @example
|
|
31
|
-
* // Listen for tracked events
|
|
32
|
-
* tracelog.on('event', (data) => {
|
|
33
|
-
* console.log('Event tracked:', data.type);
|
|
34
|
-
* });
|
|
35
|
-
*
|
|
36
|
-
* // Listen for event queues being sent
|
|
37
|
-
* tracelog.on('queue', (data) => {
|
|
38
|
-
* console.log('Events sent:', data.events.length);
|
|
39
|
-
* });
|
|
40
|
-
*/
|
|
4
|
+
export declare const event: (name: string, metadata?: Record<string, MetadataType> | Record<string, MetadataType>[]) => void;
|
|
41
5
|
export declare const on: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
|
|
42
|
-
/**
|
|
43
|
-
* Unsubscribe from events emitted by TraceLog
|
|
44
|
-
* @param event - Event name to stop listening to
|
|
45
|
-
* @param callback - The same function reference that was used in on()
|
|
46
|
-
* @example
|
|
47
|
-
* // Remove a specific listener
|
|
48
|
-
* tracelog.off('event', myCallback);
|
|
49
|
-
*/
|
|
50
6
|
export declare const off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
|
|
51
|
-
/**
|
|
52
|
-
* Checks if the app has been initialized.
|
|
53
|
-
* @returns true if the app is initialized, false otherwise
|
|
54
|
-
*/
|
|
55
7
|
export declare const isInitialized: () => boolean;
|
|
56
|
-
/**
|
|
57
|
-
* Destroys the current app instance and cleans up resources.
|
|
58
|
-
* @throws {Error} If not initialized or already destroying
|
|
59
|
-
*/
|
|
60
8
|
export declare const destroy: () => Promise<void>;
|
package/dist/esm/api.js
CHANGED
|
@@ -5,29 +5,17 @@ import './types/window.types';
|
|
|
5
5
|
let app = null;
|
|
6
6
|
let isInitializing = false;
|
|
7
7
|
let isDestroying = false;
|
|
8
|
-
/**
|
|
9
|
-
* Initializes the tracelog app with the provided configuration.
|
|
10
|
-
* If already initialized, this function returns early without error.
|
|
11
|
-
* @param appConfig - The configuration object for the app
|
|
12
|
-
* @throws {Error} If initialization fails or environment is invalid
|
|
13
|
-
* @example
|
|
14
|
-
* await tracelog.init({ id: 'my-project-id' });
|
|
15
|
-
*/
|
|
16
8
|
export const init = async (appConfig) => {
|
|
17
|
-
// Browser environment check
|
|
18
9
|
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
19
10
|
throw new Error('This library can only be used in a browser environment');
|
|
20
11
|
}
|
|
21
|
-
// Check if TraceLog is disabled
|
|
22
12
|
if (window.__traceLogDisabled) {
|
|
23
13
|
return;
|
|
24
14
|
}
|
|
25
|
-
// Already initialized - safe to return
|
|
26
15
|
if (app) {
|
|
27
16
|
debugLog.debug('API', 'Library already initialized, skipping duplicate initialization');
|
|
28
17
|
return;
|
|
29
18
|
}
|
|
30
|
-
// Prevent concurrent initialization
|
|
31
19
|
if (isInitializing) {
|
|
32
20
|
debugLog.warn('API', 'Initialization already in progress');
|
|
33
21
|
throw new Error('Initialization already in progress');
|
|
@@ -61,19 +49,6 @@ export const init = async (appConfig) => {
|
|
|
61
49
|
isInitializing = false;
|
|
62
50
|
}
|
|
63
51
|
};
|
|
64
|
-
/**
|
|
65
|
-
* Sends a custom event with the specified name and metadata.
|
|
66
|
-
* @param name - The name of the custom event.
|
|
67
|
-
* @param metadata - Optional metadata to attach to the event.
|
|
68
|
-
* @example
|
|
69
|
-
* // Send a custom event with metadata
|
|
70
|
-
* tracelog.event('user_signup', { method: 'email', plan: 'premium' });
|
|
71
|
-
* @example
|
|
72
|
-
* // Send a custom event without metadata
|
|
73
|
-
* tracelog.event('user_login');
|
|
74
|
-
* @remarks
|
|
75
|
-
* This function should be called after the app has been initialized using the `tracelog.init` function.
|
|
76
|
-
*/
|
|
77
52
|
export const event = (name, metadata) => {
|
|
78
53
|
if (!app) {
|
|
79
54
|
throw new Error('TraceLog not initialized. Please call init() first.');
|
|
@@ -86,58 +61,25 @@ export const event = (name, metadata) => {
|
|
|
86
61
|
throw error;
|
|
87
62
|
}
|
|
88
63
|
};
|
|
89
|
-
/**
|
|
90
|
-
* Subscribe to events emitted by TraceLog
|
|
91
|
-
* @param event - Event name to listen to
|
|
92
|
-
* @param callback - Function to call when event is emitted
|
|
93
|
-
* @example
|
|
94
|
-
* // Listen for tracked events
|
|
95
|
-
* tracelog.on('event', (data) => {
|
|
96
|
-
* console.log('Event tracked:', data.type);
|
|
97
|
-
* });
|
|
98
|
-
*
|
|
99
|
-
* // Listen for event queues being sent
|
|
100
|
-
* tracelog.on('queue', (data) => {
|
|
101
|
-
* console.log('Events sent:', data.events.length);
|
|
102
|
-
* });
|
|
103
|
-
*/
|
|
104
64
|
export const on = (event, callback) => {
|
|
105
65
|
if (!app) {
|
|
106
66
|
throw new Error('TraceLog not initialized. Please call init() first.');
|
|
107
67
|
}
|
|
108
68
|
app.on(event, callback);
|
|
109
69
|
};
|
|
110
|
-
/**
|
|
111
|
-
* Unsubscribe from events emitted by TraceLog
|
|
112
|
-
* @param event - Event name to stop listening to
|
|
113
|
-
* @param callback - The same function reference that was used in on()
|
|
114
|
-
* @example
|
|
115
|
-
* // Remove a specific listener
|
|
116
|
-
* tracelog.off('event', myCallback);
|
|
117
|
-
*/
|
|
118
70
|
export const off = (event, callback) => {
|
|
119
71
|
if (!app) {
|
|
120
72
|
throw new Error('TraceLog not initialized. Please call init() first.');
|
|
121
73
|
}
|
|
122
74
|
app.off(event, callback);
|
|
123
75
|
};
|
|
124
|
-
/**
|
|
125
|
-
* Checks if the app has been initialized.
|
|
126
|
-
* @returns true if the app is initialized, false otherwise
|
|
127
|
-
*/
|
|
128
76
|
export const isInitialized = () => {
|
|
129
77
|
return app !== null;
|
|
130
78
|
};
|
|
131
|
-
/**
|
|
132
|
-
* Destroys the current app instance and cleans up resources.
|
|
133
|
-
* @throws {Error} If not initialized or already destroying
|
|
134
|
-
*/
|
|
135
79
|
export const destroy = async () => {
|
|
136
|
-
// Check if app was never initialized
|
|
137
80
|
if (!app) {
|
|
138
81
|
throw new Error('App not initialized');
|
|
139
82
|
}
|
|
140
|
-
// Prevent concurrent destroy operations
|
|
141
83
|
if (isDestroying) {
|
|
142
84
|
throw new Error('Destroy operation already in progress');
|
|
143
85
|
}
|
|
@@ -160,7 +102,6 @@ export const destroy = async () => {
|
|
|
160
102
|
isDestroying = false;
|
|
161
103
|
}
|
|
162
104
|
};
|
|
163
|
-
// Auto-inject testing bridge in development environments
|
|
164
105
|
if (process.env.NODE_ENV === 'dev' && typeof window !== 'undefined') {
|
|
165
106
|
const injectTestingBridge = () => {
|
|
166
107
|
window.__traceLogBridge = new TestBridge(isInitializing, isDestroying);
|
|
@@ -2,7 +2,7 @@ export declare const PERFORMANCE_CONFIG: {
|
|
|
2
2
|
readonly WEB_VITALS_THRESHOLDS: Record<import("./types").WebVitalType, number>;
|
|
3
3
|
};
|
|
4
4
|
export declare const DATA_PROTECTION: {
|
|
5
|
-
readonly PII_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp];
|
|
5
|
+
readonly PII_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
6
6
|
};
|
|
7
7
|
export declare const ENGAGEMENT_THRESHOLDS: {
|
|
8
8
|
readonly LOW_ACTIVITY_EVENT_COUNT: 50;
|
package/dist/esm/app.d.ts
CHANGED
|
@@ -9,10 +9,6 @@ import { GoogleAnalyticsIntegration } from './integrations/google-analytics.inte
|
|
|
9
9
|
import { StorageManager } from './managers/storage.manager';
|
|
10
10
|
import { PerformanceHandler } from './handlers/performance.handler';
|
|
11
11
|
import { ErrorHandler } from './handlers/error.handler';
|
|
12
|
-
/**
|
|
13
|
-
* Main application class for TraceLog analytics
|
|
14
|
-
* Orchestrates event tracking, session management, and integrations
|
|
15
|
-
*/
|
|
16
12
|
export declare class App extends StateManager {
|
|
17
13
|
private isInitialized;
|
|
18
14
|
private suppressNextScrollTimer;
|
|
@@ -34,7 +30,7 @@ export declare class App extends StateManager {
|
|
|
34
30
|
};
|
|
35
31
|
get initialized(): boolean;
|
|
36
32
|
init(appConfig: AppConfig): Promise<void>;
|
|
37
|
-
sendCustomEvent(name: string, metadata?: Record<string, unknown>): void;
|
|
33
|
+
sendCustomEvent(name: string, metadata?: Record<string, unknown> | Record<string, unknown>[]): void;
|
|
38
34
|
on<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void;
|
|
39
35
|
off<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void;
|
|
40
36
|
destroy(force?: boolean): Promise<void>;
|
package/dist/esm/app.js
CHANGED
|
@@ -9,15 +9,11 @@ import { ClickHandler } from './handlers/click.handler';
|
|
|
9
9
|
import { ScrollHandler } from './handlers/scroll.handler';
|
|
10
10
|
import { EventType } from './types';
|
|
11
11
|
import { GoogleAnalyticsIntegration } from './integrations/google-analytics.integration';
|
|
12
|
-
import { isEventValid, getDeviceType, normalizeUrl, debugLog, Emitter
|
|
12
|
+
import { isEventValid, getDeviceType, normalizeUrl, debugLog, Emitter } from './utils';
|
|
13
13
|
import { StorageManager } from './managers/storage.manager';
|
|
14
14
|
import { SCROLL_DEBOUNCE_TIME_MS, SCROLL_SUPPRESS_MULTIPLIER } from './constants/config.constants';
|
|
15
15
|
import { PerformanceHandler } from './handlers/performance.handler';
|
|
16
16
|
import { ErrorHandler } from './handlers/error.handler';
|
|
17
|
-
/**
|
|
18
|
-
* Main application class for TraceLog analytics
|
|
19
|
-
* Orchestrates event tracking, session management, and integrations
|
|
20
|
-
*/
|
|
21
17
|
export class App extends StateManager {
|
|
22
18
|
constructor() {
|
|
23
19
|
super(...arguments);
|
|
@@ -100,6 +96,7 @@ export class App extends StateManager {
|
|
|
100
96
|
clearTimeout(this.suppressNextScrollTimer);
|
|
101
97
|
this.suppressNextScrollTimer = null;
|
|
102
98
|
}
|
|
99
|
+
this.managers.event?.flushImmediatelySync();
|
|
103
100
|
this.managers.event?.stop();
|
|
104
101
|
this.emitter.removeAllListeners();
|
|
105
102
|
this.set('hasStartSession', false);
|
|
@@ -109,20 +106,15 @@ export class App extends StateManager {
|
|
|
109
106
|
this.handlers = {};
|
|
110
107
|
}
|
|
111
108
|
async setupState(appConfig) {
|
|
112
|
-
// Set API URL
|
|
113
109
|
const apiUrl = getApiUrlForProject(appConfig.id, appConfig.allowHttp);
|
|
114
110
|
this.set('apiUrl', apiUrl);
|
|
115
|
-
// Get remote configuration
|
|
116
111
|
const configManager = new ConfigManager();
|
|
117
112
|
const config = await configManager.get(apiUrl, appConfig);
|
|
118
|
-
|
|
119
|
-
this.
|
|
120
|
-
// Set user ID
|
|
121
|
-
const userId = UserManager.getId(this.managers.storage, normalizedConfig.id);
|
|
113
|
+
this.set('config', config);
|
|
114
|
+
const userId = UserManager.getId(this.managers.storage, config.id);
|
|
122
115
|
this.set('userId', userId);
|
|
123
|
-
// Set device and page info
|
|
124
116
|
this.set('device', getDeviceType());
|
|
125
|
-
const pageUrl = normalizeUrl(window.location.href,
|
|
117
|
+
const pageUrl = normalizeUrl(window.location.href, config.sensitiveQueryParams);
|
|
126
118
|
this.set('pageUrl', pageUrl);
|
|
127
119
|
}
|
|
128
120
|
async setupIntegrations() {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import { ApiConfig
|
|
1
|
+
import { ApiConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Default API configuration values
|
|
4
|
+
* Used as fallback when API config is not available or incomplete
|
|
5
|
+
*/
|
|
2
6
|
export declare const DEFAULT_API_CONFIG: ApiConfig;
|
|
3
|
-
export declare const DEFAULT_CONFIG: (config: Config) => Config;
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import { DEFAULT_SAMPLING_RATE
|
|
1
|
+
import { DEFAULT_SAMPLING_RATE } from './config.constants';
|
|
2
|
+
/**
|
|
3
|
+
* Default API configuration values
|
|
4
|
+
* Used as fallback when API config is not available or incomplete
|
|
5
|
+
*/
|
|
2
6
|
export const DEFAULT_API_CONFIG = {
|
|
3
7
|
samplingRate: DEFAULT_SAMPLING_RATE,
|
|
4
8
|
excludedUrlPaths: [],
|
|
5
9
|
tags: [],
|
|
6
10
|
ipExcluded: false,
|
|
7
11
|
};
|
|
8
|
-
export const DEFAULT_CONFIG = (config) => ({
|
|
9
|
-
...DEFAULT_API_CONFIG,
|
|
10
|
-
...config,
|
|
11
|
-
allowHttp: false,
|
|
12
|
-
sessionTimeout: DEFAULT_SESSION_TIMEOUT,
|
|
13
|
-
samplingRate: config.samplingRate && config.samplingRate > MIN_SAMPLING_RATE && config.samplingRate <= MAX_SAMPLING_RATE
|
|
14
|
-
? config.samplingRate
|
|
15
|
-
: DEFAULT_SAMPLING_RATE,
|
|
16
|
-
excludedUrlPaths: config.excludedUrlPaths ?? [],
|
|
17
|
-
tags: config.tags ?? [],
|
|
18
|
-
ipExcluded: config.ipExcluded ?? false,
|
|
19
|
-
});
|