@armco/analytics 0.2.11 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/core/analytics.d.ts +49 -0
  2. package/core/analytics.js +354 -0
  3. package/core/errors.d.ts +26 -0
  4. package/core/errors.js +54 -0
  5. package/core/types.d.ts +137 -0
  6. package/core/types.js +1 -0
  7. package/global-modules.d.ts +14 -0
  8. package/index.d.ts +24 -0
  9. package/index.js +24 -0
  10. package/package.json +6 -36
  11. package/plugins/auto-track/click.d.ts +15 -0
  12. package/plugins/auto-track/click.js +99 -0
  13. package/plugins/auto-track/error.d.ts +15 -0
  14. package/plugins/auto-track/error.js +65 -0
  15. package/plugins/auto-track/form.d.ts +13 -0
  16. package/plugins/auto-track/form.js +54 -0
  17. package/plugins/auto-track/page.d.ts +14 -0
  18. package/plugins/auto-track/page.js +72 -0
  19. package/plugins/enrichment/session.d.ts +18 -0
  20. package/plugins/enrichment/session.js +81 -0
  21. package/plugins/enrichment/user.d.ts +20 -0
  22. package/plugins/enrichment/user.js +159 -0
  23. package/plugins/node/http-request-tracking.d.ts +54 -0
  24. package/plugins/node/http-request-tracking.js +158 -0
  25. package/storage/cookie-storage.d.ts +8 -0
  26. package/storage/cookie-storage.js +60 -0
  27. package/storage/hybrid-storage.d.ts +12 -0
  28. package/storage/hybrid-storage.js +108 -0
  29. package/storage/local-storage.d.ts +8 -0
  30. package/storage/local-storage.js +65 -0
  31. package/storage/memory-storage.d.ts +9 -0
  32. package/storage/memory-storage.js +22 -0
  33. package/transport/beacon-transport.d.ts +16 -0
  34. package/transport/beacon-transport.js +50 -0
  35. package/transport/fetch-transport.d.ts +20 -0
  36. package/transport/fetch-transport.js +112 -0
  37. package/utils/config-loader.d.ts +6 -0
  38. package/utils/config-loader.js +168 -0
  39. package/utils/helpers.d.ts +15 -0
  40. package/utils/helpers.js +148 -0
  41. package/utils/logging.d.ts +17 -0
  42. package/utils/logging.js +54 -0
  43. package/utils/validation.d.ts +9 -0
  44. package/utils/validation.js +146 -0
@@ -0,0 +1,49 @@
1
+ import type { AnalyticsConfig, IAnalytics, Plugin, EventData, PageViewEvent, ClickEvent, ErrorEvent, User, StorageManager, Transport } from "./types";
2
+ export declare class AnalyticsBuilder {
3
+ private config;
4
+ private plugins;
5
+ private storage?;
6
+ private transport?;
7
+ withApiKey(apiKey: string): this;
8
+ withEndpoint(endpoint: string): this;
9
+ withHostProjectName(name: string): this;
10
+ withLogLevel(level: AnalyticsConfig["logLevel"]): this;
11
+ withSubmissionStrategy(strategy: AnalyticsConfig["submissionStrategy"]): this;
12
+ withSamplingRate(rate: number): this;
13
+ withPlugin(plugin: Plugin): this;
14
+ withStorage(storage: StorageManager): this;
15
+ withTransport(transport: Transport): this;
16
+ withConfig(config: Partial<AnalyticsConfig>): this;
17
+ build(): Analytics;
18
+ }
19
+ export declare class Analytics implements IAnalytics {
20
+ private config;
21
+ private storage;
22
+ private transport;
23
+ private beaconTransport;
24
+ private plugins;
25
+ private logger;
26
+ private initialized;
27
+ private enabled;
28
+ private eventQueue;
29
+ private flushInterval?;
30
+ private sessionPlugin?;
31
+ private userPlugin?;
32
+ constructor(config: AnalyticsConfig, storage: StorageManager, transport: Transport, plugins: Plugin[]);
33
+ private addCorePlugins;
34
+ init(): void;
35
+ track<T extends EventData>(eventType: string, data?: T): Promise<void>;
36
+ trackPageView(data: PageViewEvent): Promise<void>;
37
+ trackClick(data: ClickEvent): Promise<void>;
38
+ trackError(data: ErrorEvent): Promise<void>;
39
+ identify(user: User): Promise<void>;
40
+ getSessionId(): string | null;
41
+ getUserId(): string | null;
42
+ private queueEvent;
43
+ private sendEvent;
44
+ flush(): Promise<void>;
45
+ private handleBeforeUnload;
46
+ private getEndpoint;
47
+ resolveEndpointAsync(): Promise<void>;
48
+ destroy(): void;
49
+ }
@@ -0,0 +1,354 @@
1
+ import { v4 as uuidv4 } from "uuid";
2
+ import { ConfigurationError, InitializationError } from "./errors";
3
+ import { HybridStorage } from "../storage/hybrid-storage";
4
+ import { MemoryStorage } from "../storage/memory-storage";
5
+ import { FetchTransport } from "../transport/fetch-transport";
6
+ import { BeaconTransport } from "../transport/beacon-transport";
7
+ import { SessionPlugin } from "../plugins/enrichment/session";
8
+ import { UserPlugin } from "../plugins/enrichment/user";
9
+ import { validateConfig, sanitizeEventData } from "../utils/validation";
10
+ import { createLogger } from "../utils/logging";
11
+ import { getEnvironmentType, isDoNotTrackEnabled, getTimestamp, deepMerge, } from "../utils/helpers";
12
+ import { resolveEndpoint, detectEnvironment } from "../utils/config-loader";
13
+ export class AnalyticsBuilder {
14
+ constructor() {
15
+ this.config = {};
16
+ this.plugins = [];
17
+ }
18
+ withApiKey(apiKey) {
19
+ this.config.apiKey = apiKey;
20
+ return this;
21
+ }
22
+ withEndpoint(endpoint) {
23
+ this.config.endpoint = endpoint;
24
+ return this;
25
+ }
26
+ withHostProjectName(name) {
27
+ this.config.hostProjectName = name;
28
+ return this;
29
+ }
30
+ withLogLevel(level) {
31
+ this.config.logLevel = level;
32
+ return this;
33
+ }
34
+ withSubmissionStrategy(strategy) {
35
+ this.config.submissionStrategy = strategy;
36
+ return this;
37
+ }
38
+ withSamplingRate(rate) {
39
+ if (rate < 0 || rate > 1) {
40
+ throw new ConfigurationError("Sampling rate must be between 0 and 1");
41
+ }
42
+ this.config.samplingRate = rate;
43
+ return this;
44
+ }
45
+ withPlugin(plugin) {
46
+ this.plugins.push(plugin);
47
+ return this;
48
+ }
49
+ withStorage(storage) {
50
+ this.storage = storage;
51
+ return this;
52
+ }
53
+ withTransport(transport) {
54
+ this.transport = transport;
55
+ return this;
56
+ }
57
+ withConfig(config) {
58
+ this.config = deepMerge(this.config, config);
59
+ return this;
60
+ }
61
+ build() {
62
+ const validatedConfig = validateConfig(this.config);
63
+ const finalConfig = {
64
+ submissionStrategy: "ONEVENT",
65
+ logLevel: "info",
66
+ samplingRate: 1,
67
+ enableLocation: false,
68
+ enableAutoTrack: true,
69
+ respectDoNotTrack: true,
70
+ batchSize: 100,
71
+ flushInterval: 15000,
72
+ maxRetries: 3,
73
+ retryDelay: 1000,
74
+ showConsentPopup: false,
75
+ maxQueueSize: 1000,
76
+ ...validatedConfig,
77
+ };
78
+ if (!finalConfig.apiKey && !finalConfig.endpoint) {
79
+ throw new ConfigurationError("Either apiKey or endpoint must be provided");
80
+ }
81
+ const storage = this.storage ||
82
+ (getEnvironmentType() === "node"
83
+ ? new MemoryStorage()
84
+ : new HybridStorage());
85
+ const transport = this.transport || new FetchTransport({
86
+ apiKey: finalConfig.apiKey,
87
+ maxRetries: finalConfig.maxRetries,
88
+ retryDelay: finalConfig.retryDelay,
89
+ });
90
+ return new Analytics(finalConfig, storage, transport, this.plugins);
91
+ }
92
+ }
93
+ export class Analytics {
94
+ constructor(config, storage, transport, plugins) {
95
+ this.plugins = [];
96
+ this.initialized = false;
97
+ this.enabled = true;
98
+ this.eventQueue = [];
99
+ this.config = config;
100
+ this.storage = storage;
101
+ this.transport = transport;
102
+ this.beaconTransport =
103
+ getEnvironmentType() === "browser"
104
+ ? new BeaconTransport({ apiKey: config.apiKey })
105
+ : null;
106
+ this.plugins = plugins;
107
+ this.logger = createLogger(config.logLevel || "info");
108
+ this.addCorePlugins();
109
+ }
110
+ addCorePlugins() {
111
+ const hasSessionPlugin = this.plugins.some((p) => p.name === "SessionPlugin");
112
+ if (!hasSessionPlugin) {
113
+ this.sessionPlugin = new SessionPlugin();
114
+ this.plugins.push(this.sessionPlugin);
115
+ }
116
+ const hasUserPlugin = this.plugins.some((p) => p.name === "UserPlugin");
117
+ if (!hasUserPlugin) {
118
+ this.userPlugin = new UserPlugin();
119
+ this.plugins.push(this.userPlugin);
120
+ }
121
+ }
122
+ init() {
123
+ if (this.initialized) {
124
+ throw new InitializationError("Analytics already initialized");
125
+ }
126
+ this.logger.info("Loading Configuration");
127
+ this.logger.info("Check if Analytics enabled");
128
+ if (this.config.respectDoNotTrack && isDoNotTrackEnabled()) {
129
+ this.logger.warn("Do Not Track is enabled, analytics will be disabled");
130
+ this.enabled = false;
131
+ return;
132
+ }
133
+ this.logger.info("Configuration loaded");
134
+ const currentEnv = this.config.environment || detectEnvironment();
135
+ this.logger.info(`Identified environment: ${currentEnv}`);
136
+ if (currentEnv !== "development" && currentEnv !== "local") {
137
+ this.logger.info("Identified non-dev environment, analytics auto load wouldn't be attempted.");
138
+ }
139
+ const context = {
140
+ config: this.config,
141
+ storage: this.storage,
142
+ transport: this.transport,
143
+ track: this.track.bind(this),
144
+ getSessionId: this.getSessionId.bind(this),
145
+ getUserId: this.getUserId.bind(this),
146
+ };
147
+ if (this.config.showConsentPopup) {
148
+ this.logger.info("Display Tracker Popup");
149
+ }
150
+ this.logger.info("Hook Event Trackers");
151
+ for (const plugin of this.plugins) {
152
+ try {
153
+ this.logger.debug(`Initializing plugin: ${plugin.name}`);
154
+ plugin.init(context);
155
+ }
156
+ catch (error) {
157
+ this.logger.error(`Failed to initialize plugin ${plugin.name}:`, error);
158
+ }
159
+ }
160
+ if (this.config.submissionStrategy === "DEFER") {
161
+ this.logger.info('Hook Handlers to flush events (use when submissionStrategy is configured as "DEFER"');
162
+ this.flushInterval = setInterval(() => {
163
+ this.flush();
164
+ }, this.config.flushInterval);
165
+ }
166
+ if (this.config.enableLocation) {
167
+ this.logger.info("Find User Location Details");
168
+ }
169
+ this.logger.info("Initiate Session and Anonymous User ID");
170
+ if (getEnvironmentType() === "browser") {
171
+ window.addEventListener("beforeunload", () => {
172
+ this.handleBeforeUnload();
173
+ });
174
+ document.addEventListener("visibilitychange", () => {
175
+ if (document.visibilityState === "hidden") {
176
+ this.handleBeforeUnload();
177
+ }
178
+ });
179
+ }
180
+ this.initialized = true;
181
+ this.logger.info("Analytics initialized");
182
+ this.track("ANALYTICS_INITIALIZED");
183
+ }
184
+ async track(eventType, data) {
185
+ if (!this.initialized) {
186
+ throw new InitializationError("Analytics not initialized. Call init() first");
187
+ }
188
+ if (!this.enabled) {
189
+ this.logger.debug("Analytics disabled, event not tracked");
190
+ return;
191
+ }
192
+ if (Math.random() > (this.config.samplingRate ?? 1)) {
193
+ this.logger.debug("Event sampled out");
194
+ return;
195
+ }
196
+ const event = {
197
+ eventType,
198
+ timestamp: getTimestamp(),
199
+ eventId: uuidv4(),
200
+ data: sanitizeEventData(data || {}),
201
+ };
202
+ for (const plugin of this.plugins) {
203
+ if (plugin.processEvent) {
204
+ try {
205
+ await plugin.processEvent(event);
206
+ }
207
+ catch (error) {
208
+ this.logger.error(`Plugin ${plugin.name} failed to process event:`, error);
209
+ }
210
+ }
211
+ }
212
+ if (this.config.submissionStrategy === "DEFER") {
213
+ this.queueEvent(event);
214
+ }
215
+ else {
216
+ await this.sendEvent(event);
217
+ }
218
+ }
219
+ async trackPageView(data) {
220
+ return this.track("PAGE_VIEW", data);
221
+ }
222
+ async trackClick(data) {
223
+ return this.track("CLICK", data);
224
+ }
225
+ async trackError(data) {
226
+ return this.track("ERROR", data);
227
+ }
228
+ async identify(user) {
229
+ if (!this.initialized) {
230
+ throw new InitializationError("Analytics not initialized. Call init() first");
231
+ }
232
+ if (this.userPlugin) {
233
+ await this.userPlugin.identify(user);
234
+ }
235
+ else {
236
+ this.logger.error("User plugin not available");
237
+ }
238
+ }
239
+ getSessionId() {
240
+ if (this.sessionPlugin) {
241
+ return this.sessionPlugin.getSessionId();
242
+ }
243
+ return null;
244
+ }
245
+ getUserId() {
246
+ if (this.userPlugin) {
247
+ return this.userPlugin.getUserId();
248
+ }
249
+ return null;
250
+ }
251
+ queueEvent(event) {
252
+ this.eventQueue.push({
253
+ event,
254
+ retries: 0,
255
+ timestamp: new Date(),
256
+ });
257
+ const maxQueueSize = this.config.maxQueueSize ?? 1000;
258
+ if (this.eventQueue.length > maxQueueSize) {
259
+ this.logger.warn(`Queue size exceeded ${maxQueueSize}, dropping oldest events`);
260
+ this.eventQueue = this.eventQueue.slice(-maxQueueSize);
261
+ }
262
+ if (this.eventQueue.length >= (this.config.batchSize ?? 100)) {
263
+ this.flush();
264
+ }
265
+ }
266
+ async sendEvent(event) {
267
+ const endpoint = this.getEndpoint();
268
+ try {
269
+ await this.transport.send(endpoint, event);
270
+ this.logger.debug("Event sent successfully:", event.eventType);
271
+ }
272
+ catch (error) {
273
+ this.logger.error("Failed to send event:", error);
274
+ }
275
+ }
276
+ async flush() {
277
+ if (this.eventQueue.length === 0) {
278
+ return;
279
+ }
280
+ const events = this.eventQueue.map((qe) => qe.event);
281
+ const endpoint = this.getEndpoint();
282
+ try {
283
+ await this.transport.sendBatch(endpoint, events);
284
+ this.logger.debug(`Flushed ${events.length} events`);
285
+ this.eventQueue = [];
286
+ }
287
+ catch (error) {
288
+ this.logger.error("Failed to flush events:", error);
289
+ }
290
+ }
291
+ handleBeforeUnload() {
292
+ if (!this.beaconTransport || this.eventQueue.length === 0) {
293
+ return;
294
+ }
295
+ const events = this.eventQueue.map((qe) => qe.event);
296
+ const endpoint = this.getEndpoint();
297
+ try {
298
+ this.beaconTransport.sendBatch(endpoint, events);
299
+ this.logger.debug("Events sent via beacon on unload");
300
+ }
301
+ catch (error) {
302
+ this.logger.error("Failed to send events on unload:", error);
303
+ }
304
+ }
305
+ getEndpoint() {
306
+ if (this.config.resolvedEndpoint) {
307
+ return this.config.resolvedEndpoint;
308
+ }
309
+ if (typeof this.config.endpoint === "string") {
310
+ return this.config.endpoint;
311
+ }
312
+ if (this.config.endpoint && typeof this.config.endpoint === "object") {
313
+ const endpoints = this.config.endpoint;
314
+ const currentEnv = this.config.environment || detectEnvironment();
315
+ if (endpoints[currentEnv]) {
316
+ return endpoints[currentEnv];
317
+ }
318
+ const fallbackOrder = ["development", "local", "staging", "production"];
319
+ for (const fallbackEnv of fallbackOrder) {
320
+ if (endpoints[fallbackEnv]) {
321
+ return endpoints[fallbackEnv];
322
+ }
323
+ }
324
+ }
325
+ if (this.config.apiKey) {
326
+ return "https://telemetry.armco.dev/events/add";
327
+ }
328
+ return "http://localhost:5001/events/add";
329
+ }
330
+ async resolveEndpointAsync() {
331
+ this.logger.info("Resolving endpoint with health check...");
332
+ const resolved = await resolveEndpoint(this.config);
333
+ this.config.resolvedEndpoint = resolved;
334
+ this.logger.info(`Resolved endpoint: ${resolved}`);
335
+ }
336
+ destroy() {
337
+ this.flush();
338
+ if (this.flushInterval) {
339
+ clearInterval(this.flushInterval);
340
+ }
341
+ for (const plugin of this.plugins) {
342
+ if (plugin.destroy) {
343
+ try {
344
+ plugin.destroy();
345
+ }
346
+ catch (error) {
347
+ this.logger.error(`Failed to destroy plugin ${plugin.name}:`, error);
348
+ }
349
+ }
350
+ }
351
+ this.initialized = false;
352
+ this.logger.info("Analytics destroyed");
353
+ }
354
+ }
@@ -0,0 +1,26 @@
1
+ export declare class AnalyticsError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare class ConfigurationError extends AnalyticsError {
5
+ constructor(message: string);
6
+ }
7
+ export declare class ValidationError extends AnalyticsError {
8
+ readonly field?: string;
9
+ readonly value?: unknown;
10
+ constructor(message: string, field?: string, value?: unknown);
11
+ }
12
+ export declare class NetworkError extends AnalyticsError {
13
+ readonly statusCode?: number;
14
+ readonly endpoint?: string;
15
+ constructor(message: string, statusCode?: number, endpoint?: string);
16
+ }
17
+ export declare class StorageError extends AnalyticsError {
18
+ constructor(message: string);
19
+ }
20
+ export declare class PluginError extends AnalyticsError {
21
+ readonly pluginName?: string;
22
+ constructor(message: string, pluginName?: string);
23
+ }
24
+ export declare class InitializationError extends AnalyticsError {
25
+ constructor(message: string);
26
+ }
package/core/errors.js ADDED
@@ -0,0 +1,54 @@
1
+ export class AnalyticsError extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = "AnalyticsError";
5
+ Object.setPrototypeOf(this, AnalyticsError.prototype);
6
+ }
7
+ }
8
+ export class ConfigurationError extends AnalyticsError {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = "ConfigurationError";
12
+ Object.setPrototypeOf(this, ConfigurationError.prototype);
13
+ }
14
+ }
15
+ export class ValidationError extends AnalyticsError {
16
+ constructor(message, field, value) {
17
+ super(message);
18
+ this.name = "ValidationError";
19
+ this.field = field;
20
+ this.value = value;
21
+ Object.setPrototypeOf(this, ValidationError.prototype);
22
+ }
23
+ }
24
+ export class NetworkError extends AnalyticsError {
25
+ constructor(message, statusCode, endpoint) {
26
+ super(message);
27
+ this.name = "NetworkError";
28
+ this.statusCode = statusCode;
29
+ this.endpoint = endpoint;
30
+ Object.setPrototypeOf(this, NetworkError.prototype);
31
+ }
32
+ }
33
+ export class StorageError extends AnalyticsError {
34
+ constructor(message) {
35
+ super(message);
36
+ this.name = "StorageError";
37
+ Object.setPrototypeOf(this, StorageError.prototype);
38
+ }
39
+ }
40
+ export class PluginError extends AnalyticsError {
41
+ constructor(message, pluginName) {
42
+ super(message);
43
+ this.name = "PluginError";
44
+ this.pluginName = pluginName;
45
+ Object.setPrototypeOf(this, PluginError.prototype);
46
+ }
47
+ }
48
+ export class InitializationError extends AnalyticsError {
49
+ constructor(message) {
50
+ super(message);
51
+ this.name = "InitializationError";
52
+ Object.setPrototypeOf(this, InitializationError.prototype);
53
+ }
54
+ }
@@ -0,0 +1,137 @@
1
+ export type Environment = "browser" | "node" | "unknown";
2
+ export type EnvironmentName = "development" | "staging" | "production" | "test" | "local" | string;
3
+ export type EndpointConfig = Record<EnvironmentName, string>;
4
+ export type SubmissionStrategy = "ONEVENT" | "DEFER";
5
+ export type LogLevel = "debug" | "info" | "warn" | "error" | "none";
6
+ export interface EventData {
7
+ [key: string]: unknown;
8
+ }
9
+ export interface TrackingEvent<T extends EventData = EventData> {
10
+ eventType: string;
11
+ timestamp: Date;
12
+ eventId: string;
13
+ sessionId?: string;
14
+ userId?: string;
15
+ data: T;
16
+ }
17
+ export interface PageViewEvent extends EventData {
18
+ pageName: string;
19
+ url: string;
20
+ referrer?: string;
21
+ title?: string;
22
+ }
23
+ export interface ClickEvent extends EventData {
24
+ elementId?: string;
25
+ elementType: string;
26
+ elementText?: string;
27
+ elementClasses?: string[];
28
+ elementPath?: string;
29
+ href?: string;
30
+ value?: string;
31
+ }
32
+ export interface FormEvent extends EventData {
33
+ formId?: string;
34
+ formName?: string;
35
+ formAction?: string;
36
+ formMethod?: string;
37
+ }
38
+ export interface ErrorEvent extends EventData {
39
+ errorMessage: string;
40
+ errorStack?: string;
41
+ errorType?: string;
42
+ }
43
+ export interface User {
44
+ email: string;
45
+ id?: string;
46
+ name?: string;
47
+ [key: string]: unknown;
48
+ }
49
+ export interface LocationData {
50
+ region?: string;
51
+ timezone?: string;
52
+ latitude?: number;
53
+ longitude?: number;
54
+ city?: string;
55
+ country?: string;
56
+ }
57
+ export interface AnalyticsConfig {
58
+ apiKey?: string;
59
+ endpoint?: string | EndpointConfig;
60
+ resolvedEndpoint?: string;
61
+ updateEndpoint?: string;
62
+ environment?: EnvironmentName;
63
+ hostProjectName?: string;
64
+ trackEvents?: string[];
65
+ submissionStrategy?: SubmissionStrategy;
66
+ showConsentPopup?: boolean;
67
+ logLevel?: LogLevel;
68
+ samplingRate?: number;
69
+ enableLocation?: boolean;
70
+ enableAutoTrack?: boolean;
71
+ respectDoNotTrack?: boolean;
72
+ batchSize?: number;
73
+ flushInterval?: number;
74
+ maxRetries?: number;
75
+ retryDelay?: number;
76
+ maxQueueSize?: number;
77
+ }
78
+ export interface ValidationResult {
79
+ valid: boolean;
80
+ errors: string[];
81
+ }
82
+ export interface Plugin {
83
+ name: string;
84
+ version?: string;
85
+ init(context: PluginContext): void | Promise<void>;
86
+ processEvent?(event: TrackingEvent): void | Promise<void>;
87
+ destroy?(): void | Promise<void>;
88
+ }
89
+ export interface PluginContext {
90
+ config: AnalyticsConfig;
91
+ storage: StorageManager;
92
+ transport: Transport;
93
+ track(eventType: string, data?: EventData): void;
94
+ getSessionId(): string | null;
95
+ getUserId(): string | null;
96
+ }
97
+ export interface StorageManager {
98
+ getItem(key: string): string | null;
99
+ setItem(key: string, value: string, options?: StorageOptions): void;
100
+ removeItem(key: string): void;
101
+ clear(): void;
102
+ }
103
+ export interface StorageOptions {
104
+ expires?: Date;
105
+ secure?: boolean;
106
+ sameSite?: "strict" | "lax" | "none";
107
+ }
108
+ export interface Transport {
109
+ send(endpoint: string, event: TrackingEvent): Promise<TransportResponse>;
110
+ sendBatch(endpoint: string, events: TrackingEvent[]): Promise<TransportResponse>;
111
+ update?(endpoint: string, payload: {
112
+ email: string;
113
+ anonymousId: string;
114
+ }): Promise<TransportResponse>;
115
+ }
116
+ export interface TransportResponse {
117
+ success: boolean;
118
+ statusCode?: number;
119
+ error?: string;
120
+ }
121
+ export interface QueuedEvent {
122
+ event: TrackingEvent;
123
+ retries: number;
124
+ timestamp: Date;
125
+ }
126
+ export interface IAnalytics {
127
+ init(): void;
128
+ track<T extends EventData>(eventType: string, data?: T): Promise<void>;
129
+ trackPageView(data: PageViewEvent): Promise<void>;
130
+ trackClick(data: ClickEvent): Promise<void>;
131
+ trackError(data: ErrorEvent): Promise<void>;
132
+ identify(user: User): Promise<void>;
133
+ getSessionId(): string | null;
134
+ getUserId(): string | null;
135
+ flush(): Promise<void>;
136
+ destroy(): void;
137
+ }
package/core/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ import analytics from "./index"
2
+
3
+ declare global {
4
+ namespace NodeJS {
5
+ interface Global {
6
+ analytics: analytics
7
+ }
8
+ }
9
+ interface Window {
10
+ analytics: analytics
11
+ }
12
+ }
13
+
14
+ export {}
package/index.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ export { Analytics, AnalyticsBuilder } from "./core/analytics";
2
+ export type { AnalyticsConfig, IAnalytics, EventData, TrackingEvent, PageViewEvent, ClickEvent, FormEvent, ErrorEvent, User, Plugin, PluginContext, StorageManager, StorageOptions, Transport, TransportResponse, LogLevel, SubmissionStrategy, Environment, } from "./core/types";
3
+ export { AnalyticsError, ConfigurationError, ValidationError, NetworkError, StorageError, PluginError, InitializationError, } from "./core/errors";
4
+ export { CookieStorage } from "./storage/cookie-storage";
5
+ export { LocalStorage } from "./storage/local-storage";
6
+ export { HybridStorage } from "./storage/hybrid-storage";
7
+ export { MemoryStorage } from "./storage/memory-storage";
8
+ export { FetchTransport } from "./transport/fetch-transport";
9
+ export { BeaconTransport } from "./transport/beacon-transport";
10
+ export { SessionPlugin } from "./plugins/enrichment/session";
11
+ export { UserPlugin } from "./plugins/enrichment/user";
12
+ export { ClickTrackingPlugin } from "./plugins/auto-track/click";
13
+ export { PageTrackingPlugin } from "./plugins/auto-track/page";
14
+ export { FormTrackingPlugin } from "./plugins/auto-track/form";
15
+ export { ErrorTrackingPlugin } from "./plugins/auto-track/error";
16
+ export { HTTPRequestTrackingPlugin } from "./plugins/node/http-request-tracking";
17
+ export type { HTTPRequestEvent, HTTPRequestMetadata } from "./plugins/node/http-request-tracking";
18
+ export { validateConfig, validateUser, validatePageView, validateClickEvent, validateFormEvent, validateErrorEvent, sanitizeEventData, } from "./utils/validation";
19
+ export { Logger, getLogger, createLogger } from "./utils/logging";
20
+ export { generateId, getEnvironmentType, getEnvironment, isDoNotTrackEnabled, isBrowser, areCookiesAvailable, isLocalStorageAvailable, debounce, throttle, deepClone, deepMerge, } from "./utils/helpers";
21
+ export { loadConfigFromFile, loadConfig, detectEnvironment, checkEndpointHealth, resolveEndpoint } from "./utils/config-loader";
22
+ import { AnalyticsBuilder as Builder } from "./core/analytics";
23
+ export declare function createAnalytics(): Builder;
24
+ export default Builder;
package/index.js ADDED
@@ -0,0 +1,24 @@
1
+ export { Analytics, AnalyticsBuilder } from "./core/analytics";
2
+ export { AnalyticsError, ConfigurationError, ValidationError, NetworkError, StorageError, PluginError, InitializationError, } from "./core/errors";
3
+ export { CookieStorage } from "./storage/cookie-storage";
4
+ export { LocalStorage } from "./storage/local-storage";
5
+ export { HybridStorage } from "./storage/hybrid-storage";
6
+ export { MemoryStorage } from "./storage/memory-storage";
7
+ export { FetchTransport } from "./transport/fetch-transport";
8
+ export { BeaconTransport } from "./transport/beacon-transport";
9
+ export { SessionPlugin } from "./plugins/enrichment/session";
10
+ export { UserPlugin } from "./plugins/enrichment/user";
11
+ export { ClickTrackingPlugin } from "./plugins/auto-track/click";
12
+ export { PageTrackingPlugin } from "./plugins/auto-track/page";
13
+ export { FormTrackingPlugin } from "./plugins/auto-track/form";
14
+ export { ErrorTrackingPlugin } from "./plugins/auto-track/error";
15
+ export { HTTPRequestTrackingPlugin } from "./plugins/node/http-request-tracking";
16
+ export { validateConfig, validateUser, validatePageView, validateClickEvent, validateFormEvent, validateErrorEvent, sanitizeEventData, } from "./utils/validation";
17
+ export { Logger, getLogger, createLogger } from "./utils/logging";
18
+ export { generateId, getEnvironmentType, getEnvironment, isDoNotTrackEnabled, isBrowser, areCookiesAvailable, isLocalStorageAvailable, debounce, throttle, deepClone, deepMerge, } from "./utils/helpers";
19
+ export { loadConfigFromFile, loadConfig, detectEnvironment, checkEndpointHealth, resolveEndpoint } from "./utils/config-loader";
20
+ import { AnalyticsBuilder as Builder } from "./core/analytics";
21
+ export function createAnalytics() {
22
+ return new Builder();
23
+ }
24
+ export default Builder;