@umituz/web-traffic 1.0.12 → 1.0.14

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/web-traffic",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "Web analytics tracking library. Event tracking, pageviews, sessions, device info, and UTM parameter support.",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "scripts": {
19
19
  "typecheck": "tsc --noEmit",
20
- "lint": "echo 'Lint passed'",
20
+ "lint": "eslint .",
21
21
  "version:patch": "npm version patch -m 'chore: release v%s'",
22
22
  "version:minor": "npm version minor -m 'chore: release v%s'",
23
23
  "version:major": "npm version major -m 'chore: release v%s'"
@@ -46,9 +46,12 @@
46
46
  "react": ">=18.2.0"
47
47
  },
48
48
  "devDependencies": {
49
+ "@eslint/js": "^9.32.0",
49
50
  "@types/react": "~19.1.10",
51
+ "eslint": "^9.32.0",
50
52
  "react": "19.1.0",
51
- "typescript": "~5.9.2"
53
+ "typescript": "~5.9.2",
54
+ "typescript-eslint": "^8.38.0"
52
55
  },
53
56
  "publishConfig": {
54
57
  "access": "public"
@@ -8,6 +8,7 @@ import type { AffiliateVisit } from '../entities/affiliate-visit.entity';
8
8
  import type { AffiliateId } from '../value-objects/affiliate-id.vo';
9
9
  import type { SiteId } from '../value-objects/site-id.vo';
10
10
  import type { SessionId } from '../../tracking/value-objects/session-id.vo';
11
+ import type { EventId } from '../../tracking/value-objects/event-id.vo';
11
12
 
12
13
  export interface IAffiliateRepository {
13
14
  save(affiliate: Affiliate): Promise<void>;
@@ -19,8 +20,8 @@ export interface IAffiliateRepository {
19
20
 
20
21
  export interface IAffiliateVisitRepository {
21
22
  save(visit: AffiliateVisit): Promise<void>;
22
- findById(id: import('../../tracking/value-objects/event-id.vo').EventId): Promise<AffiliateVisit | null>;
23
+ findById(id: EventId): Promise<AffiliateVisit | null>;
23
24
  findByAffiliate(affiliateId: AffiliateId): Promise<AffiliateVisit[]>;
24
25
  findByVisitorAndSession(visitorId: string, sessionId: SessionId): Promise<AffiliateVisit[]>;
25
- delete(id: import('../../tracking/value-objects/event-id.vo').EventId): Promise<void>;
26
+ delete(id: EventId): Promise<void>;
26
27
  }
@@ -3,9 +3,10 @@
3
3
  * @description Manages conversion order and its items
4
4
  */
5
5
 
6
- import type { OrderItem } from '../entities/order-item.entity';
6
+ import type { OrderItem, OrderItemCreateInput } from '../entities/order-item.entity';
7
7
  import type { EventId } from '../../tracking/value-objects/event-id.vo';
8
8
  import { Money } from '../value-objects/money.vo';
9
+ import { createOrderItem } from '../entities/order-item.entity';
9
10
 
10
11
  export interface OrderCreateInput {
11
12
  sessionId: string;
@@ -37,12 +38,13 @@ export class Order {
37
38
  // Calculate total and create items
38
39
  let totalAmount = 0;
39
40
  for (const item of input.items) {
40
- const orderItem: OrderItem = {
41
+ const createInput: OrderItemCreateInput = {
41
42
  id: item.id,
42
43
  name: item.name,
43
44
  price: item.price,
44
45
  quantity: item.quantity,
45
46
  };
47
+ const orderItem = createOrderItem(createInput);
46
48
  this.items.push(orderItem);
47
49
  totalAmount += item.price * item.quantity;
48
50
  }
@@ -16,6 +16,3 @@ export { Money } from './value-objects/money.vo';
16
16
 
17
17
  // Repository Interfaces
18
18
  export type { IConversionRepository } from './repositories/conversion.repository.interface';
19
-
20
- // Domain Events
21
- export { ConversionRecorded } from './events/conversion-recorded.domain-event';
@@ -25,8 +25,6 @@ export class Session {
25
25
  private endTime: number | null;
26
26
  private events: Event[];
27
27
  private pageviews: Pageview[];
28
- private eventCount: number;
29
- private pageviewCount: number;
30
28
  private entryPage: string | null;
31
29
  private exitPage: string | null;
32
30
 
@@ -39,8 +37,6 @@ export class Session {
39
37
  this.endTime = null;
40
38
  this.events = [];
41
39
  this.pageviews = [];
42
- this.eventCount = 0;
43
- this.pageviewCount = 0;
44
40
  this.entryPage = null;
45
41
  this.exitPage = null;
46
42
  Object.freeze(this.id);
@@ -56,8 +52,6 @@ export class Session {
56
52
  throw new Error('Cannot add event to expired session');
57
53
  }
58
54
  this.events.push(event);
59
- this.eventCount++;
60
- this.updateLastActivity();
61
55
  }
62
56
 
63
57
  addPageview(pageview: Pageview): void {
@@ -65,12 +59,10 @@ export class Session {
65
59
  throw new Error('Cannot add pageview to expired session');
66
60
  }
67
61
  this.pageviews.push(pageview);
68
- this.pageviewCount++;
69
62
  this.exitPage = pageview.path;
70
63
  if (!this.entryPage) {
71
64
  this.entryPage = pageview.path;
72
65
  }
73
- this.updateLastActivity();
74
66
  }
75
67
 
76
68
  getEntryPage(): string | null {
@@ -117,11 +109,11 @@ export class Session {
117
109
  }
118
110
 
119
111
  getEventCount(): number {
120
- return this.eventCount;
112
+ return this.events.length;
121
113
  }
122
114
 
123
115
  getPageviewCount(): number {
124
- return this.pageviewCount;
116
+ return this.pageviews.length;
125
117
  }
126
118
 
127
119
  getEvents(): Event[] {
@@ -132,10 +124,6 @@ export class Session {
132
124
  return [...this.pageviews];
133
125
  }
134
126
 
135
- private updateLastActivity(): void {
136
- // Could emit domain event here
137
- }
138
-
139
127
  toJSON() {
140
128
  return {
141
129
  id: this.id.toString(),
@@ -144,8 +132,8 @@ export class Session {
144
132
  deviceInfo: this.deviceInfo.toJSON(),
145
133
  startTime: this.startTime,
146
134
  endTime: this.endTime,
147
- eventCount: this.eventCount,
148
- pageviewCount: this.pageviewCount,
135
+ eventCount: this.events.length,
136
+ pageviewCount: this.pageviews.length,
149
137
  entryPage: this.entryPage,
150
138
  exitPage: this.exitPage,
151
139
  duration: this.getDuration(),
@@ -28,10 +28,6 @@ export type {
28
28
  ISessionRepository,
29
29
  } from './repositories/event.repository.interface';
30
30
 
31
- // Domain Events
32
- export { EventTracked } from './events/event-tracked.domain-event';
33
- export { PageviewTracked } from './events/pageview-tracked.domain-event';
34
-
35
31
  // Application Services
36
32
  export { TrackingCommandService } from './application/tracking-command.service';
37
33
  export type { TrackingCommandResult } from './application/tracking-command.service';
@@ -7,6 +7,7 @@ import type { Event } from '../entities/event.entity';
7
7
  import type { Pageview } from '../entities/pageview.entity';
8
8
  import type { EventId } from '../value-objects/event-id.vo';
9
9
  import type { SessionId } from '../value-objects/session-id.vo';
10
+ import type { Session } from '../aggregates/session.aggregate';
10
11
 
11
12
  export interface IEventRepository {
12
13
  save(event: Event | Pageview): Promise<void>;
@@ -16,15 +17,15 @@ export interface IEventRepository {
16
17
  }
17
18
 
18
19
  export interface IPageviewRepository {
19
- save(pageview: import('../entities/pageview.entity').Pageview): Promise<void>;
20
- findById(id: EventId): Promise<import('../entities/pageview.entity').Pageview | null>;
21
- findBySessionId(sessionId: SessionId): Promise<import('../entities/pageview.entity').Pageview[]>;
20
+ save(pageview: Pageview): Promise<void>;
21
+ findById(id: EventId): Promise<Pageview | null>;
22
+ findBySessionId(sessionId: SessionId): Promise<Pageview[]>;
22
23
  delete(id: EventId): Promise<void>;
23
24
  }
24
25
 
25
26
  export interface ISessionRepository {
26
- save(session: import('../aggregates/session.aggregate').Session): Promise<void>;
27
- findById(id: SessionId): Promise<import('../aggregates/session.aggregate').Session | null>;
28
- findActive(deviceId: string, timeoutMs: number): Promise<import('../aggregates/session.aggregate').Session | null>;
27
+ save(session: Session): Promise<void>;
28
+ findById(id: SessionId): Promise<Session | null>;
29
+ findActive(deviceId: string, timeoutMs: number): Promise<Session | null>;
29
30
  delete(id: SessionId): Promise<void>;
30
31
  }
@@ -179,12 +179,16 @@ class WebTrafficService {
179
179
  this.originalReplaceState = history.replaceState;
180
180
 
181
181
  history.pushState = (...args) => {
182
- this.originalPushState!.apply(history, args);
182
+ if (this.originalPushState) {
183
+ this.originalPushState.apply(history, args);
184
+ }
183
185
  void this.trackPageView();
184
186
  };
185
187
 
186
188
  history.replaceState = (...args) => {
187
- this.originalReplaceState!.apply(history, args);
189
+ if (this.originalReplaceState) {
190
+ this.originalReplaceState.apply(history, args);
191
+ }
188
192
  void this.trackPageView();
189
193
  };
190
194
 
@@ -8,7 +8,7 @@ import { webTrafficService, type WebTrafficConfig } from '../infrastructure/trac
8
8
  import type { WebTrafficContextValue } from './hooks';
9
9
  import type { TrackingCommandResult } from '../domains/tracking/application/tracking-command.service';
10
10
 
11
- const TrackingContext = createContext<WebTrafficContextValue | null>(null);
11
+ const WebTrafficContext = createContext<WebTrafficContextValue | null>(null);
12
12
 
13
13
  export interface WebTrafficProviderProps {
14
14
  readonly children: ReactNode;
@@ -26,10 +26,10 @@ export function WebTrafficProvider({ children, config }: WebTrafficProviderProps
26
26
 
27
27
  const value = useMemo<WebTrafficContextValue>(
28
28
  () => ({
29
- trackEvent: async (name: string, properties?: Record<string, unknown>) => {
29
+ trackEvent: (name: string, properties?: Record<string, unknown>) => {
30
30
  return webTrafficService.trackEvent(name, properties);
31
31
  },
32
- trackPageView: async (path?: string) => {
32
+ trackPageView: (path?: string) => {
33
33
  return webTrafficService.trackPageView(path);
34
34
  },
35
35
  isInitialized: webTrafficService.isInitialized(),
@@ -38,7 +38,7 @@ export function WebTrafficProvider({ children, config }: WebTrafficProviderProps
38
38
  [config]
39
39
  );
40
40
 
41
- return <TrackingContext.Provider value={value}>{children}</TrackingContext.Provider>;
41
+ return <WebTrafficContext.Provider value={value}>{children}</WebTrafficContext.Provider>;
42
42
  }
43
43
 
44
- export { TrackingContext as WebTrafficContext };
44
+ export { WebTrafficContext };
@@ -1,30 +0,0 @@
1
- /**
2
- * Conversion Recorded Domain Event
3
- * @description Published when a conversion is recorded
4
- */
5
-
6
- import type { Money } from '../value-objects/money.vo';
7
-
8
- export class ConversionRecorded {
9
- readonly eventType = 'ConversionRecorded';
10
- readonly orderId: string;
11
- readonly sessionId: string;
12
- readonly revenue: Money;
13
- readonly itemCount: number;
14
- readonly occurredAt: number;
15
-
16
- constructor(params: {
17
- orderId: string;
18
- sessionId: string;
19
- revenue: Money;
20
- itemCount: number;
21
- occurredAt?: number;
22
- }) {
23
- this.orderId = params.orderId;
24
- this.sessionId = params.sessionId;
25
- this.revenue = params.revenue;
26
- this.itemCount = params.itemCount;
27
- this.occurredAt = params.occurredAt ?? Date.now();
28
- Object.freeze(this);
29
- }
30
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * Event Tracked Domain Event
3
- * @description Published when an analytics event is tracked
4
- */
5
-
6
- import type { EventId } from '../../tracking/value-objects/event-id.vo';
7
- import type { SessionId } from '../../tracking/value-objects/session-id.vo';
8
-
9
- export class EventTracked {
10
- readonly eventType = 'EventTracked';
11
- readonly eventId: EventId;
12
- readonly sessionId: SessionId;
13
- readonly eventName: string;
14
- readonly occurredAt: number;
15
-
16
- constructor(params: {
17
- eventId: EventId;
18
- sessionId: SessionId;
19
- eventName: string;
20
- occurredAt?: number;
21
- }) {
22
- this.eventId = params.eventId;
23
- this.sessionId = params.sessionId;
24
- this.eventName = params.eventName;
25
- this.occurredAt = params.occurredAt ?? Date.now();
26
- Object.freeze(this);
27
- }
28
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * Pageview Tracked Domain Event
3
- * @description Published when a pageview is tracked
4
- */
5
-
6
- import type { EventId } from '../../tracking/value-objects/event-id.vo';
7
- import type { SessionId } from '../../tracking/value-objects/session-id.vo';
8
-
9
- export class PageviewTracked {
10
- readonly eventType = 'PageviewTracked';
11
- readonly pageviewId: EventId;
12
- readonly sessionId: SessionId;
13
- readonly path: string;
14
- readonly hasUTM: boolean;
15
- readonly occurredAt: number;
16
-
17
- constructor(params: {
18
- pageviewId: EventId;
19
- sessionId: SessionId;
20
- path: string;
21
- hasUTM: boolean;
22
- occurredAt?: number;
23
- }) {
24
- this.pageviewId = params.pageviewId;
25
- this.sessionId = params.sessionId;
26
- this.path = params.path;
27
- this.hasUTM = params.hasUTM;
28
- this.occurredAt = params.occurredAt ?? Date.now();
29
- Object.freeze(this);
30
- }
31
- }