@grainql/analytics-web 2.2.0 → 2.2.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 (83) hide show
  1. package/dist/index.global.dev.js +1 -1
  2. package/dist/index.global.js +1 -1
  3. package/dist/react/index.d.ts +44 -519
  4. package/dist/react/index.d.ts.map +1 -1
  5. package/dist/react/index.js +54 -1517
  6. package/dist/react/index.mjs +42 -1514
  7. package/package.json +1 -1
  8. package/dist/react/activity.d.ts +0 -59
  9. package/dist/react/activity.d.ts.map +0 -1
  10. package/dist/react/activity.js +0 -130
  11. package/dist/react/activity.mjs +0 -126
  12. package/dist/react/consent.d.ts +0 -72
  13. package/dist/react/consent.d.ts.map +0 -1
  14. package/dist/react/consent.js +0 -195
  15. package/dist/react/consent.mjs +0 -191
  16. package/dist/react/cookies.d.ts +0 -28
  17. package/dist/react/cookies.d.ts.map +0 -1
  18. package/dist/react/cookies.js +0 -94
  19. package/dist/react/cookies.mjs +0 -88
  20. package/dist/react/heartbeat.d.ts +0 -47
  21. package/dist/react/heartbeat.d.ts.map +0 -1
  22. package/dist/react/heartbeat.js +0 -119
  23. package/dist/react/heartbeat.mjs +0 -115
  24. package/dist/react/page-tracking.d.ts +0 -60
  25. package/dist/react/page-tracking.d.ts.map +0 -1
  26. package/dist/react/page-tracking.js +0 -179
  27. package/dist/react/page-tracking.mjs +0 -175
  28. package/dist/react/react/index.d.ts +0 -47
  29. package/dist/react/react/index.d.ts.map +0 -1
  30. package/dist/react/react/index.js +0 -58
  31. package/dist/react/react/index.mjs +0 -44
  32. /package/dist/react/{react/GrainProvider.d.ts → GrainProvider.d.ts} +0 -0
  33. /package/dist/react/{react/GrainProvider.d.ts.map → GrainProvider.d.ts.map} +0 -0
  34. /package/dist/react/{react/GrainProvider.js → GrainProvider.js} +0 -0
  35. /package/dist/react/{react/GrainProvider.mjs → GrainProvider.mjs} +0 -0
  36. /package/dist/react/{react/components → components}/ConsentBanner.d.ts +0 -0
  37. /package/dist/react/{react/components → components}/ConsentBanner.d.ts.map +0 -0
  38. /package/dist/react/{react/components → components}/ConsentBanner.js +0 -0
  39. /package/dist/react/{react/components → components}/ConsentBanner.mjs +0 -0
  40. /package/dist/react/{react/components → components}/CookieNotice.d.ts +0 -0
  41. /package/dist/react/{react/components → components}/CookieNotice.d.ts.map +0 -0
  42. /package/dist/react/{react/components → components}/CookieNotice.js +0 -0
  43. /package/dist/react/{react/components → components}/CookieNotice.mjs +0 -0
  44. /package/dist/react/{react/components → components}/PrivacyPreferenceCenter.d.ts +0 -0
  45. /package/dist/react/{react/components → components}/PrivacyPreferenceCenter.d.ts.map +0 -0
  46. /package/dist/react/{react/components → components}/PrivacyPreferenceCenter.js +0 -0
  47. /package/dist/react/{react/components → components}/PrivacyPreferenceCenter.mjs +0 -0
  48. /package/dist/react/{react/context.d.ts → context.d.ts} +0 -0
  49. /package/dist/react/{react/context.d.ts.map → context.d.ts.map} +0 -0
  50. /package/dist/react/{react/context.js → context.js} +0 -0
  51. /package/dist/react/{react/context.mjs → context.mjs} +0 -0
  52. /package/dist/react/{react/hooks → hooks}/useAllConfigs.d.ts +0 -0
  53. /package/dist/react/{react/hooks → hooks}/useAllConfigs.d.ts.map +0 -0
  54. /package/dist/react/{react/hooks → hooks}/useAllConfigs.js +0 -0
  55. /package/dist/react/{react/hooks → hooks}/useAllConfigs.mjs +0 -0
  56. /package/dist/react/{react/hooks → hooks}/useConfig.d.ts +0 -0
  57. /package/dist/react/{react/hooks → hooks}/useConfig.d.ts.map +0 -0
  58. /package/dist/react/{react/hooks → hooks}/useConfig.js +0 -0
  59. /package/dist/react/{react/hooks → hooks}/useConfig.mjs +0 -0
  60. /package/dist/react/{react/hooks → hooks}/useConsent.d.ts +0 -0
  61. /package/dist/react/{react/hooks → hooks}/useConsent.d.ts.map +0 -0
  62. /package/dist/react/{react/hooks → hooks}/useConsent.js +0 -0
  63. /package/dist/react/{react/hooks → hooks}/useConsent.mjs +0 -0
  64. /package/dist/react/{react/hooks → hooks}/useDataDeletion.d.ts +0 -0
  65. /package/dist/react/{react/hooks → hooks}/useDataDeletion.d.ts.map +0 -0
  66. /package/dist/react/{react/hooks → hooks}/useDataDeletion.js +0 -0
  67. /package/dist/react/{react/hooks → hooks}/useDataDeletion.mjs +0 -0
  68. /package/dist/react/{react/hooks → hooks}/useGrainAnalytics.d.ts +0 -0
  69. /package/dist/react/{react/hooks → hooks}/useGrainAnalytics.d.ts.map +0 -0
  70. /package/dist/react/{react/hooks → hooks}/useGrainAnalytics.js +0 -0
  71. /package/dist/react/{react/hooks → hooks}/useGrainAnalytics.mjs +0 -0
  72. /package/dist/react/{react/hooks → hooks}/usePrivacyPreferences.d.ts +0 -0
  73. /package/dist/react/{react/hooks → hooks}/usePrivacyPreferences.d.ts.map +0 -0
  74. /package/dist/react/{react/hooks → hooks}/usePrivacyPreferences.js +0 -0
  75. /package/dist/react/{react/hooks → hooks}/usePrivacyPreferences.mjs +0 -0
  76. /package/dist/react/{react/hooks → hooks}/useTrack.d.ts +0 -0
  77. /package/dist/react/{react/hooks → hooks}/useTrack.d.ts.map +0 -0
  78. /package/dist/react/{react/hooks → hooks}/useTrack.js +0 -0
  79. /package/dist/react/{react/hooks → hooks}/useTrack.mjs +0 -0
  80. /package/dist/react/{react/types.d.ts → types.d.ts} +0 -0
  81. /package/dist/react/{react/types.d.ts.map → types.d.ts.map} +0 -0
  82. /package/dist/react/{react/types.js → types.js} +0 -0
  83. /package/dist/react/{react/types.mjs → types.mjs} +0 -0
@@ -1,191 +0,0 @@
1
- /**
2
- * Consent management for Grain Analytics
3
- * Handles GDPR-compliant consent tracking and state management
4
- */
5
- export const DEFAULT_CONSENT_CATEGORIES = ['necessary', 'analytics', 'functional'];
6
- export const CONSENT_VERSION = '1.0.0';
7
- /**
8
- * Consent manager for handling user consent state
9
- */
10
- export class ConsentManager {
11
- constructor(tenantId, consentMode = 'opt-out') {
12
- this.consentState = null;
13
- this.listeners = [];
14
- this.consentMode = consentMode;
15
- this.storageKey = `grain_consent_${tenantId}`;
16
- this.loadConsentState();
17
- }
18
- /**
19
- * Load consent state from localStorage
20
- *
21
- * GDPR Compliance: In opt-in mode, we can use localStorage for consent preferences
22
- * since storing consent choices is a legitimate interest and necessary for compliance.
23
- * The consent preference itself is not tracking data.
24
- */
25
- loadConsentState() {
26
- if (typeof window === 'undefined')
27
- return;
28
- try {
29
- const stored = localStorage.getItem(this.storageKey);
30
- if (stored) {
31
- const parsed = JSON.parse(stored);
32
- this.consentState = {
33
- ...parsed,
34
- timestamp: new Date(parsed.timestamp),
35
- };
36
- }
37
- else if (this.consentMode === 'opt-out' || this.consentMode === 'disabled') {
38
- // Auto-grant consent for opt-out and disabled modes
39
- this.consentState = {
40
- granted: true,
41
- categories: DEFAULT_CONSENT_CATEGORIES,
42
- timestamp: new Date(),
43
- version: CONSENT_VERSION,
44
- };
45
- this.saveConsentState();
46
- }
47
- // Note: In opt-in mode without stored consent, consentState remains null (no consent)
48
- }
49
- catch (error) {
50
- console.error('[Grain Consent] Failed to load consent state:', error);
51
- }
52
- }
53
- /**
54
- * Save consent state to localStorage
55
- */
56
- saveConsentState() {
57
- if (typeof window === 'undefined' || !this.consentState)
58
- return;
59
- try {
60
- localStorage.setItem(this.storageKey, JSON.stringify(this.consentState));
61
- }
62
- catch (error) {
63
- console.error('[Grain Consent] Failed to save consent state:', error);
64
- }
65
- }
66
- /**
67
- * Grant consent with optional categories
68
- */
69
- grantConsent(categories) {
70
- const grantedCategories = categories || DEFAULT_CONSENT_CATEGORIES;
71
- this.consentState = {
72
- granted: true,
73
- categories: grantedCategories,
74
- timestamp: new Date(),
75
- version: CONSENT_VERSION,
76
- };
77
- this.saveConsentState();
78
- this.notifyListeners();
79
- }
80
- /**
81
- * Revoke consent (opt-out)
82
- */
83
- revokeConsent(categories) {
84
- if (!this.consentState) {
85
- this.consentState = {
86
- granted: false,
87
- categories: [],
88
- timestamp: new Date(),
89
- version: CONSENT_VERSION,
90
- };
91
- }
92
- else if (categories) {
93
- // Remove specific categories
94
- this.consentState = {
95
- ...this.consentState,
96
- categories: this.consentState.categories.filter(cat => !categories.includes(cat)),
97
- granted: this.consentState.categories.length > 0,
98
- timestamp: new Date(),
99
- };
100
- }
101
- else {
102
- // Revoke all consent
103
- this.consentState = {
104
- granted: false,
105
- categories: [],
106
- timestamp: new Date(),
107
- version: CONSENT_VERSION,
108
- };
109
- }
110
- this.saveConsentState();
111
- this.notifyListeners();
112
- }
113
- /**
114
- * Get current consent state
115
- */
116
- getConsentState() {
117
- return this.consentState ? { ...this.consentState } : null;
118
- }
119
- /**
120
- * Check if user has granted consent
121
- */
122
- hasConsent(category) {
123
- // Disabled mode always returns true (no consent required)
124
- if (this.consentMode === 'disabled') {
125
- return true;
126
- }
127
- // No consent state in opt-in mode means no consent
128
- if (this.consentMode === 'opt-in' && !this.consentState) {
129
- return false;
130
- }
131
- // Check consent state
132
- if (!this.consentState?.granted) {
133
- return false;
134
- }
135
- // Check specific category if provided
136
- if (category) {
137
- return this.consentState.categories.includes(category);
138
- }
139
- return true;
140
- }
141
- /**
142
- * Check if we should wait for consent before tracking
143
- */
144
- shouldWaitForConsent() {
145
- return this.consentMode === 'opt-in' && !this.consentState?.granted;
146
- }
147
- /**
148
- * Add consent change listener
149
- */
150
- addListener(listener) {
151
- this.listeners.push(listener);
152
- }
153
- /**
154
- * Remove consent change listener
155
- */
156
- removeListener(listener) {
157
- const index = this.listeners.indexOf(listener);
158
- if (index > -1) {
159
- this.listeners.splice(index, 1);
160
- }
161
- }
162
- /**
163
- * Notify all listeners of consent state change
164
- */
165
- notifyListeners() {
166
- if (!this.consentState)
167
- return;
168
- this.listeners.forEach(listener => {
169
- try {
170
- listener(this.consentState);
171
- }
172
- catch (error) {
173
- console.error('[Grain Consent] Listener error:', error);
174
- }
175
- });
176
- }
177
- /**
178
- * Clear all consent data
179
- */
180
- clearConsent() {
181
- if (typeof window === 'undefined')
182
- return;
183
- try {
184
- localStorage.removeItem(this.storageKey);
185
- this.consentState = null;
186
- }
187
- catch (error) {
188
- console.error('[Grain Consent] Failed to clear consent:', error);
189
- }
190
- }
191
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * Cookie utilities for Grain Analytics
3
- * Provides GDPR-compliant cookie management with configurable options
4
- */
5
- export interface CookieConfig {
6
- domain?: string;
7
- path?: string;
8
- sameSite?: 'strict' | 'lax' | 'none';
9
- secure?: boolean;
10
- maxAge?: number;
11
- }
12
- /**
13
- * Set a cookie with configurable options
14
- */
15
- export declare function setCookie(name: string, value: string, config?: CookieConfig): void;
16
- /**
17
- * Get a cookie value by name
18
- */
19
- export declare function getCookie(name: string): string | null;
20
- /**
21
- * Delete a cookie by name
22
- */
23
- export declare function deleteCookie(name: string, config?: Pick<CookieConfig, 'domain' | 'path'>): void;
24
- /**
25
- * Check if cookies are available and working
26
- */
27
- export declare function areCookiesEnabled(): boolean;
28
- //# sourceMappingURL=cookies.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/cookies.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CA4BlF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBrD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,MAAM,CAAC,GAAG,IAAI,CAmB/F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAY3C"}
@@ -1,94 +0,0 @@
1
- "use strict";
2
- /**
3
- * Cookie utilities for Grain Analytics
4
- * Provides GDPR-compliant cookie management with configurable options
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.setCookie = setCookie;
8
- exports.getCookie = getCookie;
9
- exports.deleteCookie = deleteCookie;
10
- exports.areCookiesEnabled = areCookiesEnabled;
11
- /**
12
- * Set a cookie with configurable options
13
- */
14
- function setCookie(name, value, config) {
15
- if (typeof document === 'undefined')
16
- return;
17
- const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
18
- if (config?.maxAge !== undefined) {
19
- parts.push(`max-age=${config.maxAge}`);
20
- }
21
- if (config?.domain) {
22
- parts.push(`domain=${config.domain}`);
23
- }
24
- if (config?.path) {
25
- parts.push(`path=${config.path}`);
26
- }
27
- else {
28
- parts.push('path=/');
29
- }
30
- if (config?.sameSite) {
31
- parts.push(`samesite=${config.sameSite}`);
32
- }
33
- if (config?.secure) {
34
- parts.push('secure');
35
- }
36
- document.cookie = parts.join('; ');
37
- }
38
- /**
39
- * Get a cookie value by name
40
- */
41
- function getCookie(name) {
42
- if (typeof document === 'undefined')
43
- return null;
44
- const nameEQ = encodeURIComponent(name) + '=';
45
- const cookies = document.cookie.split(';');
46
- for (let i = 0; i < cookies.length; i++) {
47
- let cookie = cookies[i];
48
- while (cookie.charAt(0) === ' ') {
49
- cookie = cookie.substring(1);
50
- }
51
- if (cookie.indexOf(nameEQ) === 0) {
52
- return decodeURIComponent(cookie.substring(nameEQ.length));
53
- }
54
- }
55
- return null;
56
- }
57
- /**
58
- * Delete a cookie by name
59
- */
60
- function deleteCookie(name, config) {
61
- if (typeof document === 'undefined')
62
- return;
63
- const parts = [
64
- `${encodeURIComponent(name)}=`,
65
- 'max-age=0',
66
- ];
67
- if (config?.domain) {
68
- parts.push(`domain=${config.domain}`);
69
- }
70
- if (config?.path) {
71
- parts.push(`path=${config.path}`);
72
- }
73
- else {
74
- parts.push('path=/');
75
- }
76
- document.cookie = parts.join('; ');
77
- }
78
- /**
79
- * Check if cookies are available and working
80
- */
81
- function areCookiesEnabled() {
82
- if (typeof document === 'undefined')
83
- return false;
84
- try {
85
- const testCookie = '_grain_cookie_test';
86
- setCookie(testCookie, 'test', { maxAge: 1 });
87
- const result = getCookie(testCookie) === 'test';
88
- deleteCookie(testCookie);
89
- return result;
90
- }
91
- catch {
92
- return false;
93
- }
94
- }
@@ -1,88 +0,0 @@
1
- /**
2
- * Cookie utilities for Grain Analytics
3
- * Provides GDPR-compliant cookie management with configurable options
4
- */
5
- /**
6
- * Set a cookie with configurable options
7
- */
8
- export function setCookie(name, value, config) {
9
- if (typeof document === 'undefined')
10
- return;
11
- const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
12
- if (config?.maxAge !== undefined) {
13
- parts.push(`max-age=${config.maxAge}`);
14
- }
15
- if (config?.domain) {
16
- parts.push(`domain=${config.domain}`);
17
- }
18
- if (config?.path) {
19
- parts.push(`path=${config.path}`);
20
- }
21
- else {
22
- parts.push('path=/');
23
- }
24
- if (config?.sameSite) {
25
- parts.push(`samesite=${config.sameSite}`);
26
- }
27
- if (config?.secure) {
28
- parts.push('secure');
29
- }
30
- document.cookie = parts.join('; ');
31
- }
32
- /**
33
- * Get a cookie value by name
34
- */
35
- export function getCookie(name) {
36
- if (typeof document === 'undefined')
37
- return null;
38
- const nameEQ = encodeURIComponent(name) + '=';
39
- const cookies = document.cookie.split(';');
40
- for (let i = 0; i < cookies.length; i++) {
41
- let cookie = cookies[i];
42
- while (cookie.charAt(0) === ' ') {
43
- cookie = cookie.substring(1);
44
- }
45
- if (cookie.indexOf(nameEQ) === 0) {
46
- return decodeURIComponent(cookie.substring(nameEQ.length));
47
- }
48
- }
49
- return null;
50
- }
51
- /**
52
- * Delete a cookie by name
53
- */
54
- export function deleteCookie(name, config) {
55
- if (typeof document === 'undefined')
56
- return;
57
- const parts = [
58
- `${encodeURIComponent(name)}=`,
59
- 'max-age=0',
60
- ];
61
- if (config?.domain) {
62
- parts.push(`domain=${config.domain}`);
63
- }
64
- if (config?.path) {
65
- parts.push(`path=${config.path}`);
66
- }
67
- else {
68
- parts.push('path=/');
69
- }
70
- document.cookie = parts.join('; ');
71
- }
72
- /**
73
- * Check if cookies are available and working
74
- */
75
- export function areCookiesEnabled() {
76
- if (typeof document === 'undefined')
77
- return false;
78
- try {
79
- const testCookie = '_grain_cookie_test';
80
- setCookie(testCookie, 'test', { maxAge: 1 });
81
- const result = getCookie(testCookie) === 'test';
82
- deleteCookie(testCookie);
83
- return result;
84
- }
85
- catch {
86
- return false;
87
- }
88
- }
@@ -1,47 +0,0 @@
1
- /**
2
- * Heartbeat Manager for Grain Analytics
3
- * Tracks session activity with consent-aware behavior
4
- */
5
- import type { ActivityDetector } from './activity';
6
- export interface HeartbeatConfig {
7
- activeInterval: number;
8
- inactiveInterval: number;
9
- debug?: boolean;
10
- }
11
- export interface HeartbeatTracker {
12
- trackSystemEvent(eventName: string, properties: Record<string, unknown>): void;
13
- hasConsent(category?: string): boolean;
14
- getEffectiveUserId(): string;
15
- getEphemeralSessionId(): string;
16
- getCurrentPage(): string | null;
17
- getEventCountSinceLastHeartbeat(): number;
18
- resetEventCountSinceLastHeartbeat(): void;
19
- }
20
- export declare class HeartbeatManager {
21
- private config;
22
- private tracker;
23
- private activityDetector;
24
- private heartbeatTimer;
25
- private isDestroyed;
26
- private lastHeartbeatTime;
27
- private currentInterval;
28
- private hasSentPageLoadHeartbeat;
29
- constructor(tracker: HeartbeatTracker, activityDetector: ActivityDetector, config: HeartbeatConfig);
30
- /**
31
- * Send initial heartbeat when page loads
32
- */
33
- private sendPageLoadHeartbeat;
34
- /**
35
- * Schedule the next heartbeat based on current activity
36
- */
37
- private scheduleNextHeartbeat;
38
- /**
39
- * Send heartbeat event
40
- */
41
- private sendHeartbeat;
42
- /**
43
- * Destroy the heartbeat manager
44
- */
45
- destroy(): void;
46
- }
47
- //# sourceMappingURL=heartbeat.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../../src/heartbeat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/E,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,kBAAkB,IAAI,MAAM,CAAC;IAC7B,qBAAqB,IAAI,MAAM,CAAC;IAChC,cAAc,IAAI,MAAM,GAAG,IAAI,CAAC;IAChC,+BAA+B,IAAI,MAAM,CAAC;IAC1C,iCAAiC,IAAI,IAAI,CAAC;CAC3C;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,wBAAwB,CAAS;gBAGvC,OAAO,EAAE,gBAAgB,EACzB,gBAAgB,EAAE,gBAAgB,EAClC,MAAM,EAAE,eAAe;IAezB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAkB7B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAyB7B;;OAEG;IACH,OAAO,CAAC,aAAa;IA0CrB;;OAEG;IACH,OAAO,IAAI,IAAI;CAchB"}
@@ -1,119 +0,0 @@
1
- "use strict";
2
- /**
3
- * Heartbeat Manager for Grain Analytics
4
- * Tracks session activity with consent-aware behavior
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.HeartbeatManager = void 0;
8
- class HeartbeatManager {
9
- constructor(tracker, activityDetector, config) {
10
- this.heartbeatTimer = null;
11
- this.isDestroyed = false;
12
- this.hasSentPageLoadHeartbeat = false;
13
- this.tracker = tracker;
14
- this.activityDetector = activityDetector;
15
- this.config = config;
16
- this.lastHeartbeatTime = Date.now();
17
- this.currentInterval = config.activeInterval;
18
- // Send initial heartbeat when page loads (if allowed by consent)
19
- this.sendPageLoadHeartbeat();
20
- // Start periodic heartbeat tracking
21
- this.scheduleNextHeartbeat();
22
- }
23
- /**
24
- * Send initial heartbeat when page loads
25
- */
26
- sendPageLoadHeartbeat() {
27
- if (this.isDestroyed || this.hasSentPageLoadHeartbeat)
28
- return;
29
- // Wait for page to be fully loaded
30
- if (typeof window !== 'undefined' && document.readyState !== 'complete') {
31
- const handleLoad = () => {
32
- this.sendHeartbeat('page_load');
33
- this.hasSentPageLoadHeartbeat = true;
34
- window.removeEventListener('load', handleLoad);
35
- };
36
- window.addEventListener('load', handleLoad);
37
- }
38
- else {
39
- // Page is already loaded or we're in a non-browser environment
40
- this.sendHeartbeat('page_load');
41
- this.hasSentPageLoadHeartbeat = true;
42
- }
43
- }
44
- /**
45
- * Schedule the next heartbeat based on current activity
46
- */
47
- scheduleNextHeartbeat() {
48
- if (this.isDestroyed)
49
- return;
50
- // Clear existing timer
51
- if (this.heartbeatTimer !== null) {
52
- clearTimeout(this.heartbeatTimer);
53
- }
54
- // Determine interval based on activity
55
- const isActive = this.activityDetector.isActive(60000); // 1 minute threshold
56
- this.currentInterval = isActive ? this.config.activeInterval : this.config.inactiveInterval;
57
- // Schedule next heartbeat
58
- this.heartbeatTimer = window.setTimeout(() => {
59
- this.sendHeartbeat('periodic');
60
- this.scheduleNextHeartbeat();
61
- }, this.currentInterval);
62
- if (this.config.debug) {
63
- console.log(`[Heartbeat] Scheduled next heartbeat in ${this.currentInterval / 1000}s (${isActive ? 'active' : 'inactive'})`);
64
- }
65
- }
66
- /**
67
- * Send heartbeat event
68
- */
69
- sendHeartbeat(heartbeatType = 'periodic') {
70
- if (this.isDestroyed)
71
- return;
72
- const now = Date.now();
73
- const isActive = this.activityDetector.isActive(60000); // 1 minute threshold
74
- const hasConsent = this.tracker.hasConsent('analytics');
75
- // Base properties (always included)
76
- const properties = {
77
- type: 'heartbeat',
78
- heartbeat_type: heartbeatType,
79
- status: isActive ? 'active' : 'inactive',
80
- timestamp: now,
81
- };
82
- // Enhanced properties when consent is granted
83
- if (hasConsent) {
84
- const page = this.tracker.getCurrentPage();
85
- if (page) {
86
- properties.page = page;
87
- }
88
- // Only include duration and event count for periodic heartbeats
89
- if (heartbeatType === 'periodic') {
90
- properties.duration = now - this.lastHeartbeatTime;
91
- properties.event_count = this.tracker.getEventCountSinceLastHeartbeat();
92
- // Reset event count
93
- this.tracker.resetEventCountSinceLastHeartbeat();
94
- }
95
- }
96
- // Track the heartbeat event
97
- this.tracker.trackSystemEvent('_grain_heartbeat', properties);
98
- this.lastHeartbeatTime = now;
99
- if (this.config.debug) {
100
- console.log('[Heartbeat] Sent heartbeat:', properties);
101
- }
102
- }
103
- /**
104
- * Destroy the heartbeat manager
105
- */
106
- destroy() {
107
- if (this.isDestroyed)
108
- return;
109
- if (this.heartbeatTimer !== null) {
110
- clearTimeout(this.heartbeatTimer);
111
- this.heartbeatTimer = null;
112
- }
113
- this.isDestroyed = true;
114
- if (this.config.debug) {
115
- console.log('[Heartbeat] Destroyed');
116
- }
117
- }
118
- }
119
- exports.HeartbeatManager = HeartbeatManager;
@@ -1,115 +0,0 @@
1
- /**
2
- * Heartbeat Manager for Grain Analytics
3
- * Tracks session activity with consent-aware behavior
4
- */
5
- export class HeartbeatManager {
6
- constructor(tracker, activityDetector, config) {
7
- this.heartbeatTimer = null;
8
- this.isDestroyed = false;
9
- this.hasSentPageLoadHeartbeat = false;
10
- this.tracker = tracker;
11
- this.activityDetector = activityDetector;
12
- this.config = config;
13
- this.lastHeartbeatTime = Date.now();
14
- this.currentInterval = config.activeInterval;
15
- // Send initial heartbeat when page loads (if allowed by consent)
16
- this.sendPageLoadHeartbeat();
17
- // Start periodic heartbeat tracking
18
- this.scheduleNextHeartbeat();
19
- }
20
- /**
21
- * Send initial heartbeat when page loads
22
- */
23
- sendPageLoadHeartbeat() {
24
- if (this.isDestroyed || this.hasSentPageLoadHeartbeat)
25
- return;
26
- // Wait for page to be fully loaded
27
- if (typeof window !== 'undefined' && document.readyState !== 'complete') {
28
- const handleLoad = () => {
29
- this.sendHeartbeat('page_load');
30
- this.hasSentPageLoadHeartbeat = true;
31
- window.removeEventListener('load', handleLoad);
32
- };
33
- window.addEventListener('load', handleLoad);
34
- }
35
- else {
36
- // Page is already loaded or we're in a non-browser environment
37
- this.sendHeartbeat('page_load');
38
- this.hasSentPageLoadHeartbeat = true;
39
- }
40
- }
41
- /**
42
- * Schedule the next heartbeat based on current activity
43
- */
44
- scheduleNextHeartbeat() {
45
- if (this.isDestroyed)
46
- return;
47
- // Clear existing timer
48
- if (this.heartbeatTimer !== null) {
49
- clearTimeout(this.heartbeatTimer);
50
- }
51
- // Determine interval based on activity
52
- const isActive = this.activityDetector.isActive(60000); // 1 minute threshold
53
- this.currentInterval = isActive ? this.config.activeInterval : this.config.inactiveInterval;
54
- // Schedule next heartbeat
55
- this.heartbeatTimer = window.setTimeout(() => {
56
- this.sendHeartbeat('periodic');
57
- this.scheduleNextHeartbeat();
58
- }, this.currentInterval);
59
- if (this.config.debug) {
60
- console.log(`[Heartbeat] Scheduled next heartbeat in ${this.currentInterval / 1000}s (${isActive ? 'active' : 'inactive'})`);
61
- }
62
- }
63
- /**
64
- * Send heartbeat event
65
- */
66
- sendHeartbeat(heartbeatType = 'periodic') {
67
- if (this.isDestroyed)
68
- return;
69
- const now = Date.now();
70
- const isActive = this.activityDetector.isActive(60000); // 1 minute threshold
71
- const hasConsent = this.tracker.hasConsent('analytics');
72
- // Base properties (always included)
73
- const properties = {
74
- type: 'heartbeat',
75
- heartbeat_type: heartbeatType,
76
- status: isActive ? 'active' : 'inactive',
77
- timestamp: now,
78
- };
79
- // Enhanced properties when consent is granted
80
- if (hasConsent) {
81
- const page = this.tracker.getCurrentPage();
82
- if (page) {
83
- properties.page = page;
84
- }
85
- // Only include duration and event count for periodic heartbeats
86
- if (heartbeatType === 'periodic') {
87
- properties.duration = now - this.lastHeartbeatTime;
88
- properties.event_count = this.tracker.getEventCountSinceLastHeartbeat();
89
- // Reset event count
90
- this.tracker.resetEventCountSinceLastHeartbeat();
91
- }
92
- }
93
- // Track the heartbeat event
94
- this.tracker.trackSystemEvent('_grain_heartbeat', properties);
95
- this.lastHeartbeatTime = now;
96
- if (this.config.debug) {
97
- console.log('[Heartbeat] Sent heartbeat:', properties);
98
- }
99
- }
100
- /**
101
- * Destroy the heartbeat manager
102
- */
103
- destroy() {
104
- if (this.isDestroyed)
105
- return;
106
- if (this.heartbeatTimer !== null) {
107
- clearTimeout(this.heartbeatTimer);
108
- this.heartbeatTimer = null;
109
- }
110
- this.isDestroyed = true;
111
- if (this.config.debug) {
112
- console.log('[Heartbeat] Destroyed');
113
- }
114
- }
115
- }