@grainql/analytics-web 1.7.4 → 2.1.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/README.md +71 -718
- package/dist/activity.d.ts +59 -0
- package/dist/activity.d.ts.map +1 -0
- package/dist/cjs/activity.d.ts +59 -0
- package/dist/cjs/activity.d.ts.map +1 -0
- package/dist/cjs/activity.js +131 -0
- package/dist/cjs/activity.js.map +1 -0
- package/dist/cjs/consent.d.ts +68 -0
- package/dist/cjs/consent.d.ts.map +1 -0
- package/dist/cjs/consent.js +191 -0
- package/dist/cjs/consent.js.map +1 -0
- package/dist/cjs/cookies.d.ts +28 -0
- package/dist/cjs/cookies.d.ts.map +1 -0
- package/dist/cjs/cookies.js +95 -0
- package/dist/cjs/cookies.js.map +1 -0
- package/dist/cjs/heartbeat.d.ts +42 -0
- package/dist/cjs/heartbeat.d.ts.map +1 -0
- package/dist/cjs/heartbeat.js +92 -0
- package/dist/cjs/heartbeat.js.map +1 -0
- package/dist/cjs/index.d.ts +100 -3
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/page-tracking.d.ts +60 -0
- package/dist/cjs/page-tracking.d.ts.map +1 -0
- package/dist/cjs/page-tracking.js +180 -0
- package/dist/cjs/page-tracking.js.map +1 -0
- package/dist/cjs/react/GrainProvider.d.ts +11 -0
- package/dist/cjs/react/GrainProvider.d.ts.map +1 -0
- package/dist/cjs/react/GrainProvider.js +79 -0
- package/dist/cjs/react/GrainProvider.js.map +1 -0
- package/dist/cjs/react/components/ConsentBanner.d.ts +16 -0
- package/dist/cjs/react/components/ConsentBanner.d.ts.map +1 -0
- package/dist/cjs/react/components/ConsentBanner.js +112 -0
- package/dist/cjs/react/components/ConsentBanner.js.map +1 -0
- package/dist/cjs/react/components/CookieNotice.d.ts +12 -0
- package/dist/cjs/react/components/CookieNotice.d.ts.map +1 -0
- package/dist/cjs/react/components/CookieNotice.js +62 -0
- package/dist/cjs/react/components/CookieNotice.js.map +1 -0
- package/dist/cjs/react/components/PrivacyPreferenceCenter.d.ts +12 -0
- package/dist/cjs/react/components/PrivacyPreferenceCenter.d.ts.map +1 -0
- package/dist/cjs/react/components/PrivacyPreferenceCenter.js +120 -0
- package/dist/cjs/react/components/PrivacyPreferenceCenter.js.map +1 -0
- package/dist/cjs/react/context.d.ts +11 -0
- package/dist/cjs/react/context.d.ts.map +1 -0
- package/dist/cjs/react/context.js +43 -0
- package/dist/cjs/react/context.js.map +1 -0
- package/dist/cjs/react/hooks/useAllConfigs.d.ts +8 -0
- package/dist/cjs/react/hooks/useAllConfigs.d.ts.map +1 -0
- package/dist/cjs/react/hooks/useAllConfigs.js +112 -0
- package/dist/cjs/react/hooks/useAllConfigs.js.map +1 -0
- package/dist/cjs/react/hooks/useConfig.d.ts +9 -0
- package/dist/cjs/react/hooks/useConfig.d.ts.map +1 -0
- package/dist/cjs/react/hooks/useConfig.js +116 -0
- package/dist/cjs/react/hooks/useConfig.js.map +1 -0
- package/dist/cjs/react/hooks/useConsent.d.ts +13 -0
- package/dist/cjs/react/hooks/useConsent.d.ts.map +1 -0
- package/dist/cjs/react/hooks/useConsent.js +84 -0
- package/dist/cjs/react/hooks/useConsent.js.map +1 -0
- package/dist/cjs/react/hooks/useDataDeletion.d.ts +17 -0
- package/dist/cjs/react/hooks/useDataDeletion.d.ts.map +1 -0
- package/dist/cjs/react/hooks/useDataDeletion.js +117 -0
- package/dist/cjs/react/hooks/useDataDeletion.js.map +1 -0
- package/dist/cjs/react/hooks/useGrainAnalytics.d.ts +6 -0
- package/dist/cjs/react/hooks/useGrainAnalytics.d.ts.map +1 -0
- package/dist/cjs/react/hooks/useGrainAnalytics.js +50 -0
- package/dist/cjs/react/hooks/useGrainAnalytics.js.map +1 -0
- package/dist/cjs/react/hooks/usePrivacyPreferences.d.ts +15 -0
- package/dist/cjs/react/hooks/usePrivacyPreferences.d.ts.map +1 -0
- package/dist/cjs/react/hooks/usePrivacyPreferences.js +82 -0
- package/dist/cjs/react/hooks/usePrivacyPreferences.js.map +1 -0
- package/dist/cjs/react/hooks/useTrack.d.ts +9 -0
- package/dist/cjs/react/hooks/useTrack.d.ts.map +1 -0
- package/dist/cjs/react/hooks/useTrack.js +53 -0
- package/dist/cjs/react/hooks/useTrack.js.map +1 -0
- package/dist/cjs/react/index.d.ts +47 -0
- package/dist/cjs/react/index.d.ts.map +1 -0
- package/dist/cjs/react/index.js +59 -0
- package/dist/cjs/react/index.js.map +1 -0
- package/dist/cjs/react/types.d.ts +33 -0
- package/dist/cjs/react/types.d.ts.map +1 -0
- package/dist/cjs/react/types.js +6 -0
- package/dist/cjs/react/types.js.map +1 -0
- package/dist/consent.d.ts +68 -0
- package/dist/consent.d.ts.map +1 -0
- package/dist/cookies.d.ts +28 -0
- package/dist/cookies.d.ts.map +1 -0
- package/dist/esm/activity.d.ts +59 -0
- package/dist/esm/activity.d.ts.map +1 -0
- package/dist/esm/activity.js +127 -0
- package/dist/esm/activity.js.map +1 -0
- package/dist/esm/consent.d.ts +68 -0
- package/dist/esm/consent.d.ts.map +1 -0
- package/dist/esm/consent.js +187 -0
- package/dist/esm/consent.js.map +1 -0
- package/dist/esm/cookies.d.ts +28 -0
- package/dist/esm/cookies.d.ts.map +1 -0
- package/dist/esm/cookies.js +89 -0
- package/dist/esm/cookies.js.map +1 -0
- package/dist/esm/heartbeat.d.ts +42 -0
- package/dist/esm/heartbeat.d.ts.map +1 -0
- package/dist/esm/heartbeat.js +88 -0
- package/dist/esm/heartbeat.js.map +1 -0
- package/dist/esm/index.d.ts +100 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/page-tracking.d.ts +60 -0
- package/dist/esm/page-tracking.d.ts.map +1 -0
- package/dist/esm/page-tracking.js +176 -0
- package/dist/esm/page-tracking.js.map +1 -0
- package/dist/esm/react/GrainProvider.d.ts +11 -0
- package/dist/esm/react/GrainProvider.d.ts.map +1 -0
- package/dist/esm/react/GrainProvider.js +43 -0
- package/dist/esm/react/GrainProvider.js.map +1 -0
- package/dist/esm/react/components/ConsentBanner.d.ts +16 -0
- package/dist/esm/react/components/ConsentBanner.d.ts.map +1 -0
- package/dist/esm/react/components/ConsentBanner.js +76 -0
- package/dist/esm/react/components/ConsentBanner.js.map +1 -0
- package/dist/esm/react/components/CookieNotice.d.ts +12 -0
- package/dist/esm/react/components/CookieNotice.d.ts.map +1 -0
- package/dist/esm/react/components/CookieNotice.js +26 -0
- package/dist/esm/react/components/CookieNotice.js.map +1 -0
- package/dist/esm/react/components/PrivacyPreferenceCenter.d.ts +12 -0
- package/dist/esm/react/components/PrivacyPreferenceCenter.d.ts.map +1 -0
- package/dist/esm/react/components/PrivacyPreferenceCenter.js +84 -0
- package/dist/esm/react/components/PrivacyPreferenceCenter.js.map +1 -0
- package/dist/esm/react/context.d.ts +11 -0
- package/dist/esm/react/context.d.ts.map +1 -0
- package/dist/esm/react/context.js +7 -0
- package/dist/esm/react/context.js.map +1 -0
- package/dist/esm/react/hooks/useAllConfigs.d.ts +8 -0
- package/dist/esm/react/hooks/useAllConfigs.d.ts.map +1 -0
- package/dist/esm/react/hooks/useAllConfigs.js +76 -0
- package/dist/esm/react/hooks/useAllConfigs.js.map +1 -0
- package/dist/esm/react/hooks/useConfig.d.ts +9 -0
- package/dist/esm/react/hooks/useConfig.d.ts.map +1 -0
- package/dist/esm/react/hooks/useConfig.js +80 -0
- package/dist/esm/react/hooks/useConfig.js.map +1 -0
- package/dist/esm/react/hooks/useConsent.d.ts +13 -0
- package/dist/esm/react/hooks/useConsent.d.ts.map +1 -0
- package/dist/esm/react/hooks/useConsent.js +48 -0
- package/dist/esm/react/hooks/useConsent.js.map +1 -0
- package/dist/esm/react/hooks/useDataDeletion.d.ts +17 -0
- package/dist/esm/react/hooks/useDataDeletion.d.ts.map +1 -0
- package/dist/esm/react/hooks/useDataDeletion.js +81 -0
- package/dist/esm/react/hooks/useDataDeletion.js.map +1 -0
- package/dist/esm/react/hooks/useGrainAnalytics.d.ts +6 -0
- package/dist/esm/react/hooks/useGrainAnalytics.d.ts.map +1 -0
- package/dist/esm/react/hooks/useGrainAnalytics.js +14 -0
- package/dist/esm/react/hooks/useGrainAnalytics.js.map +1 -0
- package/dist/esm/react/hooks/usePrivacyPreferences.d.ts +15 -0
- package/dist/esm/react/hooks/usePrivacyPreferences.d.ts.map +1 -0
- package/dist/esm/react/hooks/usePrivacyPreferences.js +46 -0
- package/dist/esm/react/hooks/usePrivacyPreferences.js.map +1 -0
- package/dist/esm/react/hooks/useTrack.d.ts +9 -0
- package/dist/esm/react/hooks/useTrack.d.ts.map +1 -0
- package/dist/esm/react/hooks/useTrack.js +17 -0
- package/dist/esm/react/hooks/useTrack.js.map +1 -0
- package/dist/esm/react/index.d.ts +47 -0
- package/dist/esm/react/index.d.ts.map +1 -0
- package/dist/esm/react/index.js +45 -0
- package/dist/esm/react/index.js.map +1 -0
- package/dist/esm/react/types.d.ts +33 -0
- package/dist/esm/react/types.d.ts.map +1 -0
- package/dist/esm/react/types.js +5 -0
- package/dist/esm/react/types.js.map +1 -0
- package/dist/heartbeat.d.ts +42 -0
- package/dist/heartbeat.d.ts.map +1 -0
- package/dist/index.d.ts +100 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.global.dev.js +903 -12
- package/dist/index.global.dev.js.map +3 -3
- package/dist/index.global.js +2 -2
- package/dist/index.global.js.map +4 -4
- package/dist/index.js +321 -11
- package/dist/index.mjs +321 -11
- package/dist/page-tracking.d.ts +60 -0
- package/dist/page-tracking.d.ts.map +1 -0
- package/dist/react/activity.d.ts +59 -0
- package/dist/react/activity.d.ts.map +1 -0
- package/dist/react/activity.js +130 -0
- package/dist/react/activity.mjs +126 -0
- package/dist/react/consent.d.ts +68 -0
- package/dist/react/consent.d.ts.map +1 -0
- package/dist/react/consent.js +190 -0
- package/dist/react/consent.mjs +186 -0
- package/dist/react/cookies.d.ts +28 -0
- package/dist/react/cookies.d.ts.map +1 -0
- package/dist/react/cookies.js +94 -0
- package/dist/react/cookies.mjs +88 -0
- package/dist/react/heartbeat.d.ts +42 -0
- package/dist/react/heartbeat.d.ts.map +1 -0
- package/dist/react/heartbeat.js +91 -0
- package/dist/react/heartbeat.mjs +87 -0
- package/dist/react/index.d.ts +502 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +1491 -0
- package/dist/react/index.mjs +1486 -0
- package/dist/react/page-tracking.d.ts +60 -0
- package/dist/react/page-tracking.d.ts.map +1 -0
- package/dist/react/page-tracking.js +179 -0
- package/dist/react/page-tracking.mjs +175 -0
- package/dist/react/react/GrainProvider.d.ts +11 -0
- package/dist/react/react/GrainProvider.d.ts.map +1 -0
- package/dist/react/react/GrainProvider.js +45 -0
- package/dist/react/react/GrainProvider.mjs +42 -0
- package/dist/react/react/components/ConsentBanner.d.ts +16 -0
- package/dist/react/react/components/ConsentBanner.d.ts.map +1 -0
- package/dist/react/react/components/ConsentBanner.js +78 -0
- package/dist/react/react/components/ConsentBanner.mjs +75 -0
- package/dist/react/react/components/CookieNotice.d.ts +12 -0
- package/dist/react/react/components/CookieNotice.d.ts.map +1 -0
- package/dist/react/react/components/CookieNotice.js +28 -0
- package/dist/react/react/components/CookieNotice.mjs +25 -0
- package/dist/react/react/components/PrivacyPreferenceCenter.d.ts +12 -0
- package/dist/react/react/components/PrivacyPreferenceCenter.d.ts.map +1 -0
- package/dist/react/react/components/PrivacyPreferenceCenter.js +86 -0
- package/dist/react/react/components/PrivacyPreferenceCenter.mjs +83 -0
- package/dist/react/react/context.d.ts +11 -0
- package/dist/react/react/context.d.ts.map +1 -0
- package/dist/react/react/context.js +9 -0
- package/dist/react/react/context.mjs +6 -0
- package/dist/react/react/hooks/useAllConfigs.d.ts +8 -0
- package/dist/react/react/hooks/useAllConfigs.d.ts.map +1 -0
- package/dist/react/react/hooks/useAllConfigs.js +78 -0
- package/dist/react/react/hooks/useAllConfigs.mjs +75 -0
- package/dist/react/react/hooks/useConfig.d.ts +9 -0
- package/dist/react/react/hooks/useConfig.d.ts.map +1 -0
- package/dist/react/react/hooks/useConfig.js +82 -0
- package/dist/react/react/hooks/useConfig.mjs +79 -0
- package/dist/react/react/hooks/useConsent.d.ts +13 -0
- package/dist/react/react/hooks/useConsent.d.ts.map +1 -0
- package/dist/react/react/hooks/useConsent.js +50 -0
- package/dist/react/react/hooks/useConsent.mjs +47 -0
- package/dist/react/react/hooks/useDataDeletion.d.ts +17 -0
- package/dist/react/react/hooks/useDataDeletion.d.ts.map +1 -0
- package/dist/react/react/hooks/useDataDeletion.js +83 -0
- package/dist/react/react/hooks/useDataDeletion.mjs +80 -0
- package/dist/react/react/hooks/useGrainAnalytics.d.ts +6 -0
- package/dist/react/react/hooks/useGrainAnalytics.d.ts.map +1 -0
- package/dist/react/react/hooks/useGrainAnalytics.js +16 -0
- package/dist/react/react/hooks/useGrainAnalytics.mjs +13 -0
- package/dist/react/react/hooks/usePrivacyPreferences.d.ts +15 -0
- package/dist/react/react/hooks/usePrivacyPreferences.d.ts.map +1 -0
- package/dist/react/react/hooks/usePrivacyPreferences.js +48 -0
- package/dist/react/react/hooks/usePrivacyPreferences.mjs +45 -0
- package/dist/react/react/hooks/useTrack.d.ts +9 -0
- package/dist/react/react/hooks/useTrack.d.ts.map +1 -0
- package/dist/react/react/hooks/useTrack.js +19 -0
- package/dist/react/react/hooks/useTrack.mjs +16 -0
- package/dist/react/react/index.d.ts +47 -0
- package/dist/react/react/index.d.ts.map +1 -0
- package/dist/react/react/index.js +58 -0
- package/dist/react/react/index.mjs +44 -0
- package/dist/react/react/types.d.ts +33 -0
- package/dist/react/react/types.d.ts.map +1 -0
- package/dist/react/react/types.js +5 -0
- package/dist/react/react/types.mjs +4 -0
- package/package.json +20 -2
|
@@ -0,0 +1,28 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
constructor(tracker: HeartbeatTracker, activityDetector: ActivityDetector, config: HeartbeatConfig);
|
|
29
|
+
/**
|
|
30
|
+
* Schedule the next heartbeat based on current activity
|
|
31
|
+
*/
|
|
32
|
+
private scheduleNextHeartbeat;
|
|
33
|
+
/**
|
|
34
|
+
* Send heartbeat event
|
|
35
|
+
*/
|
|
36
|
+
private sendHeartbeat;
|
|
37
|
+
/**
|
|
38
|
+
* Destroy the heartbeat manager
|
|
39
|
+
*/
|
|
40
|
+
destroy(): void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=heartbeat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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;gBAG9B,OAAO,EAAE,gBAAgB,EACzB,gBAAgB,EAAE,gBAAgB,EAClC,MAAM,EAAE,eAAe;IAYzB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAyB7B;;OAEG;IACH,OAAO,CAAC,aAAa;IAqCrB;;OAEG;IACH,OAAO,IAAI,IAAI;CAchB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
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.tracker = tracker;
|
|
13
|
+
this.activityDetector = activityDetector;
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.lastHeartbeatTime = Date.now();
|
|
16
|
+
this.currentInterval = config.activeInterval;
|
|
17
|
+
// Start heartbeat tracking
|
|
18
|
+
this.scheduleNextHeartbeat();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Schedule the next heartbeat based on current activity
|
|
22
|
+
*/
|
|
23
|
+
scheduleNextHeartbeat() {
|
|
24
|
+
if (this.isDestroyed)
|
|
25
|
+
return;
|
|
26
|
+
// Clear existing timer
|
|
27
|
+
if (this.heartbeatTimer !== null) {
|
|
28
|
+
clearTimeout(this.heartbeatTimer);
|
|
29
|
+
}
|
|
30
|
+
// Determine interval based on activity
|
|
31
|
+
const isActive = this.activityDetector.isActive(60000); // 1 minute threshold
|
|
32
|
+
this.currentInterval = isActive ? this.config.activeInterval : this.config.inactiveInterval;
|
|
33
|
+
// Schedule next heartbeat
|
|
34
|
+
this.heartbeatTimer = window.setTimeout(() => {
|
|
35
|
+
this.sendHeartbeat();
|
|
36
|
+
this.scheduleNextHeartbeat();
|
|
37
|
+
}, this.currentInterval);
|
|
38
|
+
if (this.config.debug) {
|
|
39
|
+
console.log(`[Heartbeat] Scheduled next heartbeat in ${this.currentInterval / 1000}s (${isActive ? 'active' : 'inactive'})`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Send heartbeat event
|
|
44
|
+
*/
|
|
45
|
+
sendHeartbeat() {
|
|
46
|
+
if (this.isDestroyed)
|
|
47
|
+
return;
|
|
48
|
+
const now = Date.now();
|
|
49
|
+
const isActive = this.activityDetector.isActive(60000); // 1 minute threshold
|
|
50
|
+
const hasConsent = this.tracker.hasConsent('analytics');
|
|
51
|
+
// Base properties (always included)
|
|
52
|
+
const properties = {
|
|
53
|
+
type: 'heartbeat',
|
|
54
|
+
status: isActive ? 'active' : 'inactive',
|
|
55
|
+
timestamp: now,
|
|
56
|
+
};
|
|
57
|
+
// Enhanced properties when consent is granted
|
|
58
|
+
if (hasConsent) {
|
|
59
|
+
const page = this.tracker.getCurrentPage();
|
|
60
|
+
if (page) {
|
|
61
|
+
properties.page = page;
|
|
62
|
+
}
|
|
63
|
+
properties.duration = now - this.lastHeartbeatTime;
|
|
64
|
+
properties.event_count = this.tracker.getEventCountSinceLastHeartbeat();
|
|
65
|
+
// Reset event count
|
|
66
|
+
this.tracker.resetEventCountSinceLastHeartbeat();
|
|
67
|
+
}
|
|
68
|
+
// Track the heartbeat event
|
|
69
|
+
this.tracker.trackSystemEvent('_grain_heartbeat', properties);
|
|
70
|
+
this.lastHeartbeatTime = now;
|
|
71
|
+
if (this.config.debug) {
|
|
72
|
+
console.log('[Heartbeat] Sent heartbeat:', properties);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Destroy the heartbeat manager
|
|
77
|
+
*/
|
|
78
|
+
destroy() {
|
|
79
|
+
if (this.isDestroyed)
|
|
80
|
+
return;
|
|
81
|
+
if (this.heartbeatTimer !== null) {
|
|
82
|
+
clearTimeout(this.heartbeatTimer);
|
|
83
|
+
this.heartbeatTimer = null;
|
|
84
|
+
}
|
|
85
|
+
this.isDestroyed = true;
|
|
86
|
+
if (this.config.debug) {
|
|
87
|
+
console.log('[Heartbeat] Destroyed');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.HeartbeatManager = HeartbeatManager;
|
|
@@ -0,0 +1,87 @@
|
|
|
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.tracker = tracker;
|
|
10
|
+
this.activityDetector = activityDetector;
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.lastHeartbeatTime = Date.now();
|
|
13
|
+
this.currentInterval = config.activeInterval;
|
|
14
|
+
// Start heartbeat tracking
|
|
15
|
+
this.scheduleNextHeartbeat();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Schedule the next heartbeat based on current activity
|
|
19
|
+
*/
|
|
20
|
+
scheduleNextHeartbeat() {
|
|
21
|
+
if (this.isDestroyed)
|
|
22
|
+
return;
|
|
23
|
+
// Clear existing timer
|
|
24
|
+
if (this.heartbeatTimer !== null) {
|
|
25
|
+
clearTimeout(this.heartbeatTimer);
|
|
26
|
+
}
|
|
27
|
+
// Determine interval based on activity
|
|
28
|
+
const isActive = this.activityDetector.isActive(60000); // 1 minute threshold
|
|
29
|
+
this.currentInterval = isActive ? this.config.activeInterval : this.config.inactiveInterval;
|
|
30
|
+
// Schedule next heartbeat
|
|
31
|
+
this.heartbeatTimer = window.setTimeout(() => {
|
|
32
|
+
this.sendHeartbeat();
|
|
33
|
+
this.scheduleNextHeartbeat();
|
|
34
|
+
}, this.currentInterval);
|
|
35
|
+
if (this.config.debug) {
|
|
36
|
+
console.log(`[Heartbeat] Scheduled next heartbeat in ${this.currentInterval / 1000}s (${isActive ? 'active' : 'inactive'})`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Send heartbeat event
|
|
41
|
+
*/
|
|
42
|
+
sendHeartbeat() {
|
|
43
|
+
if (this.isDestroyed)
|
|
44
|
+
return;
|
|
45
|
+
const now = Date.now();
|
|
46
|
+
const isActive = this.activityDetector.isActive(60000); // 1 minute threshold
|
|
47
|
+
const hasConsent = this.tracker.hasConsent('analytics');
|
|
48
|
+
// Base properties (always included)
|
|
49
|
+
const properties = {
|
|
50
|
+
type: 'heartbeat',
|
|
51
|
+
status: isActive ? 'active' : 'inactive',
|
|
52
|
+
timestamp: now,
|
|
53
|
+
};
|
|
54
|
+
// Enhanced properties when consent is granted
|
|
55
|
+
if (hasConsent) {
|
|
56
|
+
const page = this.tracker.getCurrentPage();
|
|
57
|
+
if (page) {
|
|
58
|
+
properties.page = page;
|
|
59
|
+
}
|
|
60
|
+
properties.duration = now - this.lastHeartbeatTime;
|
|
61
|
+
properties.event_count = this.tracker.getEventCountSinceLastHeartbeat();
|
|
62
|
+
// Reset event count
|
|
63
|
+
this.tracker.resetEventCountSinceLastHeartbeat();
|
|
64
|
+
}
|
|
65
|
+
// Track the heartbeat event
|
|
66
|
+
this.tracker.trackSystemEvent('_grain_heartbeat', properties);
|
|
67
|
+
this.lastHeartbeatTime = now;
|
|
68
|
+
if (this.config.debug) {
|
|
69
|
+
console.log('[Heartbeat] Sent heartbeat:', properties);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Destroy the heartbeat manager
|
|
74
|
+
*/
|
|
75
|
+
destroy() {
|
|
76
|
+
if (this.isDestroyed)
|
|
77
|
+
return;
|
|
78
|
+
if (this.heartbeatTimer !== null) {
|
|
79
|
+
clearTimeout(this.heartbeatTimer);
|
|
80
|
+
this.heartbeatTimer = null;
|
|
81
|
+
}
|
|
82
|
+
this.isDestroyed = true;
|
|
83
|
+
if (this.config.debug) {
|
|
84
|
+
console.log('[Heartbeat] Destroyed');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|