@tracetail/react 2.3.14 → 2.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +31 -2
- package/dist/index.esm.js +37 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { FC, ReactNode } from 'react';
|
|
9
9
|
import { FingerprintOptions, FingerprintResult } from '@tracetail/js';
|
|
10
|
+
import type { ComplianceContext } from '@tracetail/js';
|
|
10
11
|
export interface UseTraceTailOptions extends FingerprintOptions {
|
|
11
12
|
immediate?: boolean;
|
|
12
13
|
suspense?: boolean;
|
|
@@ -70,8 +71,35 @@ export declare function useVisitorId(options: UseTraceTailOptions & {
|
|
|
70
71
|
error: Error | null;
|
|
71
72
|
refresh: () => Promise<void>;
|
|
72
73
|
};
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
/**
|
|
75
|
+
* React hook returning client-side privacy / region compliance signals.
|
|
76
|
+
*
|
|
77
|
+
* The context is computed ONCE on mount (the underlying signals — timezone,
|
|
78
|
+
* locale, GPC, DNT — do not change during a session) and memoized for the
|
|
79
|
+
* lifetime of the component. SSR-safe: during server render it returns the same
|
|
80
|
+
* safe defaults as `getComplianceContext()`.
|
|
81
|
+
*
|
|
82
|
+
* These are CLIENT-SIDE HEURISTICS, not authoritative geolocation, and do NOT
|
|
83
|
+
* gate or alter fingerprint collection. Use `likelyRequiresConsent` together
|
|
84
|
+
* with your own consent state to decide whether to collect a fingerprint —
|
|
85
|
+
* obtaining consent where required (EU ePrivacy/GDPR, UK PECR, etc.) is the
|
|
86
|
+
* merchant's responsibility.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* import { useComplianceContext, useTraceTail } from '@tracetail/react';
|
|
91
|
+
*
|
|
92
|
+
* function Tracker({ hasConsent }: { hasConsent: boolean }) {
|
|
93
|
+
* const compliance = useComplianceContext();
|
|
94
|
+
* const shouldCollect = !compliance.likelyRequiresConsent || hasConsent;
|
|
95
|
+
* const { fingerprint } = useTraceTail({ immediate: shouldCollect });
|
|
96
|
+
* return shouldCollect ? <span>{fingerprint?.visitorId}</span> : null;
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare function useComplianceContext(): ComplianceContext;
|
|
101
|
+
export type { FingerprintOptions, FingerprintResult, ComponentData, ComplianceContext, ComplianceRegion } from '@tracetail/js';
|
|
102
|
+
export { TraceTail, getComplianceContext } from '@tracetail/js';
|
|
75
103
|
interface TraceTailProviderProps {
|
|
76
104
|
children: ReactNode;
|
|
77
105
|
apiKey: string;
|
|
@@ -85,6 +113,7 @@ export declare const getVersion: () => string;
|
|
|
85
113
|
declare const _default: {
|
|
86
114
|
useTraceTail: typeof useTraceTail;
|
|
87
115
|
useVisitorId: typeof useVisitorId;
|
|
116
|
+
useComplianceContext: typeof useComplianceContext;
|
|
88
117
|
TraceTailProvider: FC<TraceTailProviderProps>;
|
|
89
118
|
getVersion: () => string;
|
|
90
119
|
};
|
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
-
import { TraceTail } from '@tracetail/js';
|
|
4
|
-
export { TraceTail } from '@tracetail/js';
|
|
2
|
+
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
3
|
+
import { TraceTail, getComplianceContext } from '@tracetail/js';
|
|
4
|
+
export { TraceTail, getComplianceContext } from '@tracetail/js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* React hook for basic browser fingerprinting
|
|
@@ -131,6 +131,38 @@ function useVisitorId(options) {
|
|
|
131
131
|
refresh
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* React hook returning client-side privacy / region compliance signals.
|
|
136
|
+
*
|
|
137
|
+
* The context is computed ONCE on mount (the underlying signals — timezone,
|
|
138
|
+
* locale, GPC, DNT — do not change during a session) and memoized for the
|
|
139
|
+
* lifetime of the component. SSR-safe: during server render it returns the same
|
|
140
|
+
* safe defaults as `getComplianceContext()`.
|
|
141
|
+
*
|
|
142
|
+
* These are CLIENT-SIDE HEURISTICS, not authoritative geolocation, and do NOT
|
|
143
|
+
* gate or alter fingerprint collection. Use `likelyRequiresConsent` together
|
|
144
|
+
* with your own consent state to decide whether to collect a fingerprint —
|
|
145
|
+
* obtaining consent where required (EU ePrivacy/GDPR, UK PECR, etc.) is the
|
|
146
|
+
* merchant's responsibility.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* import { useComplianceContext, useTraceTail } from '@tracetail/react';
|
|
151
|
+
*
|
|
152
|
+
* function Tracker({ hasConsent }: { hasConsent: boolean }) {
|
|
153
|
+
* const compliance = useComplianceContext();
|
|
154
|
+
* const shouldCollect = !compliance.likelyRequiresConsent || hasConsent;
|
|
155
|
+
* const { fingerprint } = useTraceTail({ immediate: shouldCollect });
|
|
156
|
+
* return shouldCollect ? <span>{fingerprint?.visitorId}</span> : null;
|
|
157
|
+
* }
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
function useComplianceContext() {
|
|
161
|
+
// Empty dependency list: compute once and keep the same reference for the
|
|
162
|
+
// component's lifetime. useMemo (rather than useState/useEffect) keeps the
|
|
163
|
+
// value available on the very first render, including during SSR.
|
|
164
|
+
return useMemo(() => getComplianceContext(), []);
|
|
165
|
+
}
|
|
134
166
|
const TraceTailProvider = ({ children }) => {
|
|
135
167
|
// This is a simple provider that could be extended with context
|
|
136
168
|
// For now, it just renders children since hooks manage their own instances
|
|
@@ -144,9 +176,10 @@ const getVersion = () => '2.3.4';
|
|
|
144
176
|
var index = {
|
|
145
177
|
useTraceTail,
|
|
146
178
|
useVisitorId,
|
|
179
|
+
useComplianceContext,
|
|
147
180
|
TraceTailProvider,
|
|
148
181
|
getVersion
|
|
149
182
|
};
|
|
150
183
|
|
|
151
|
-
export { TraceTailProvider, index as default, getVersion, useTraceTail, useVisitorId };
|
|
184
|
+
export { TraceTailProvider, index as default, getVersion, useComplianceContext, useTraceTail, useVisitorId };
|
|
152
185
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @tracetail/react - React Hooks for Enterprise Browser Fingerprinting\n * Version: 2.3.4\n *\n * Over 99.5% accuracy browser fingerprinting with React hooks and server-side processing.\n * Perfect for fraud detection, user analytics, and security applications.\n */\n\nimport { useEffect, useState, useCallback, useRef } from 'react';\nimport type { FC, ReactNode } from 'react';\nimport { TraceTail, FingerprintOptions, FingerprintResult } from '@tracetail/js';\n\nexport interface UseTraceTailOptions extends FingerprintOptions {\n immediate?: boolean;\n suspense?: boolean;\n}\n\nexport interface UseTraceTailReturn {\n fingerprint: FingerprintResult | null;\n loading: boolean;\n error: Error | null;\n generate: () => Promise<FingerprintResult>;\n regenerate: () => Promise<FingerprintResult>;\n}\n\n\n/**\n * React hook for basic browser fingerprinting\n * \n * @example\n * ```typescript\n * import { useTraceTail } from '@tracetail/react';\n * \n * function MyComponent() {\n * const { fingerprint, loading, error } = useTraceTail({\n * apiKey: 'your-api-key',\n * immediate: true\n * });\n * \n * if (loading) return <div>Generating fingerprint...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return <div>Visitor ID: {fingerprint?.visitorId}</div>;\n * }\n * ```\n */\nexport function useTraceTail(options: UseTraceTailOptions): UseTraceTailReturn {\n const [fingerprint, setFingerprint] = useState<FingerprintResult | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n \n const traceTailRef = useRef<TraceTail | null>(null);\n \n // Initialize TraceTail instance\n useEffect(() => {\n if (!traceTailRef.current) {\n traceTailRef.current = new TraceTail(options);\n }\n }, [options.apiKey, options.endpoint]);\n\n const generate = useCallback(async (): Promise<FingerprintResult> => {\n if (!traceTailRef.current) {\n throw new Error('TraceTail not initialized');\n }\n\n setLoading(true);\n setError(null);\n\n try {\n const result = await traceTailRef.current.generateFingerprint({\n verbose: true\n });\n setFingerprint(result);\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Unknown error');\n setError(error);\n throw error;\n } finally {\n setLoading(false);\n }\n }, []);\n\n const regenerate = useCallback(async (): Promise<FingerprintResult> => {\n setFingerprint(null);\n return generate();\n }, [generate]);\n\n // Auto-generate on mount if immediate is true\n useEffect(() => {\n if (options.immediate && !fingerprint && !loading) {\n generate().catch(() => {\n // Error is already handled in generate function\n });\n }\n }, [options.immediate, fingerprint, loading, generate]);\n\n return {\n fingerprint,\n loading,\n error,\n generate,\n regenerate\n };\n}\n\n\n/**\n * React hook for visitor identification with persistent storage\n * \n * @example\n * ```typescript\n * import { useVisitorId } from '@tracetail/react';\n * \n * function UserTrackingComponent() {\n * const { visitorId, isReturningVisitor, loading } = useVisitorId({\n * apiKey: 'your-api-key',\n * storageKey: 'app_visitor_id'\n * });\n * \n * return (\n * <div>\n * <p>Visitor: {visitorId}</p>\n * <p>Status: {isReturningVisitor ? 'Returning' : 'New'} visitor</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useVisitorId(options: UseTraceTailOptions & {\n storageKey?: string;\n}): {\n visitorId: string | null;\n isReturningVisitor: boolean;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n} {\n const storageKey = options.storageKey || 'tracetail_visitor_id';\n const [visitorId, setVisitorId] = useState<string | null>(null);\n const [isReturningVisitor, setIsReturningVisitor] = useState(false);\n \n const { fingerprint, loading, error, generate } = useTraceTail({\n ...options,\n immediate: true\n });\n\n // Update visitor ID when fingerprint changes\n useEffect(() => {\n if (fingerprint?.visitorId) {\n const storedVisitorId = localStorage.getItem(storageKey);\n \n if (storedVisitorId) {\n setIsReturningVisitor(storedVisitorId === fingerprint.visitorId);\n } else {\n setIsReturningVisitor(false);\n }\n \n setVisitorId(fingerprint.visitorId);\n localStorage.setItem(storageKey, fingerprint.visitorId);\n }\n }, [fingerprint?.visitorId, storageKey]);\n\n const refresh = useCallback(async () => {\n await generate();\n }, [generate]);\n\n return {\n visitorId,\n isReturningVisitor,\n loading,\n error,\n refresh\n };\n}\n\n\n// Re-export types and utilities from the base package\nexport type {\n FingerprintOptions,\n FingerprintResult,\n ComponentData\n} from '@tracetail/js';\n\nexport { TraceTail } from '@tracetail/js';\n\n// React-specific utilities\ninterface TraceTailProviderProps {\n children: ReactNode;\n apiKey: string;\n options?: Partial<FingerprintOptions>;\n}\n\nexport const TraceTailProvider: FC<TraceTailProviderProps> = ({ children }) => {\n // This is a simple provider that could be extended with context\n // For now, it just renders children since hooks manage their own instances\n return <>{children}</>;\n};\n\n/**\n * Get the current React package version\n */\nexport const getVersion = (): string => '2.3.4';\n\n// Default export\nexport default {\n useTraceTail,\n useVisitorId,\n TraceTailProvider,\n getVersion\n};"],"names":["_jsx","_Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @tracetail/react - React Hooks for Enterprise Browser Fingerprinting\n * Version: 2.3.4\n *\n * Over 99.5% accuracy browser fingerprinting with React hooks and server-side processing.\n * Perfect for fraud detection, user analytics, and security applications.\n */\n\nimport { useEffect, useState, useCallback, useRef, useMemo } from 'react';\nimport type { FC, ReactNode } from 'react';\nimport {\n TraceTail,\n FingerprintOptions,\n FingerprintResult,\n getComplianceContext,\n} from '@tracetail/js';\nimport type { ComplianceContext } from '@tracetail/js';\n\nexport interface UseTraceTailOptions extends FingerprintOptions {\n immediate?: boolean;\n suspense?: boolean;\n}\n\nexport interface UseTraceTailReturn {\n fingerprint: FingerprintResult | null;\n loading: boolean;\n error: Error | null;\n generate: () => Promise<FingerprintResult>;\n regenerate: () => Promise<FingerprintResult>;\n}\n\n\n/**\n * React hook for basic browser fingerprinting\n * \n * @example\n * ```typescript\n * import { useTraceTail } from '@tracetail/react';\n * \n * function MyComponent() {\n * const { fingerprint, loading, error } = useTraceTail({\n * apiKey: 'your-api-key',\n * immediate: true\n * });\n * \n * if (loading) return <div>Generating fingerprint...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return <div>Visitor ID: {fingerprint?.visitorId}</div>;\n * }\n * ```\n */\nexport function useTraceTail(options: UseTraceTailOptions): UseTraceTailReturn {\n const [fingerprint, setFingerprint] = useState<FingerprintResult | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n \n const traceTailRef = useRef<TraceTail | null>(null);\n \n // Initialize TraceTail instance\n useEffect(() => {\n if (!traceTailRef.current) {\n traceTailRef.current = new TraceTail(options);\n }\n }, [options.apiKey, options.endpoint]);\n\n const generate = useCallback(async (): Promise<FingerprintResult> => {\n if (!traceTailRef.current) {\n throw new Error('TraceTail not initialized');\n }\n\n setLoading(true);\n setError(null);\n\n try {\n const result = await traceTailRef.current.generateFingerprint({\n verbose: true\n });\n setFingerprint(result);\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Unknown error');\n setError(error);\n throw error;\n } finally {\n setLoading(false);\n }\n }, []);\n\n const regenerate = useCallback(async (): Promise<FingerprintResult> => {\n setFingerprint(null);\n return generate();\n }, [generate]);\n\n // Auto-generate on mount if immediate is true\n useEffect(() => {\n if (options.immediate && !fingerprint && !loading) {\n generate().catch(() => {\n // Error is already handled in generate function\n });\n }\n }, [options.immediate, fingerprint, loading, generate]);\n\n return {\n fingerprint,\n loading,\n error,\n generate,\n regenerate\n };\n}\n\n\n/**\n * React hook for visitor identification with persistent storage\n * \n * @example\n * ```typescript\n * import { useVisitorId } from '@tracetail/react';\n * \n * function UserTrackingComponent() {\n * const { visitorId, isReturningVisitor, loading } = useVisitorId({\n * apiKey: 'your-api-key',\n * storageKey: 'app_visitor_id'\n * });\n * \n * return (\n * <div>\n * <p>Visitor: {visitorId}</p>\n * <p>Status: {isReturningVisitor ? 'Returning' : 'New'} visitor</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useVisitorId(options: UseTraceTailOptions & {\n storageKey?: string;\n}): {\n visitorId: string | null;\n isReturningVisitor: boolean;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n} {\n const storageKey = options.storageKey || 'tracetail_visitor_id';\n const [visitorId, setVisitorId] = useState<string | null>(null);\n const [isReturningVisitor, setIsReturningVisitor] = useState(false);\n \n const { fingerprint, loading, error, generate } = useTraceTail({\n ...options,\n immediate: true\n });\n\n // Update visitor ID when fingerprint changes\n useEffect(() => {\n if (fingerprint?.visitorId) {\n const storedVisitorId = localStorage.getItem(storageKey);\n \n if (storedVisitorId) {\n setIsReturningVisitor(storedVisitorId === fingerprint.visitorId);\n } else {\n setIsReturningVisitor(false);\n }\n \n setVisitorId(fingerprint.visitorId);\n localStorage.setItem(storageKey, fingerprint.visitorId);\n }\n }, [fingerprint?.visitorId, storageKey]);\n\n const refresh = useCallback(async () => {\n await generate();\n }, [generate]);\n\n return {\n visitorId,\n isReturningVisitor,\n loading,\n error,\n refresh\n };\n}\n\n\n/**\n * React hook returning client-side privacy / region compliance signals.\n *\n * The context is computed ONCE on mount (the underlying signals — timezone,\n * locale, GPC, DNT — do not change during a session) and memoized for the\n * lifetime of the component. SSR-safe: during server render it returns the same\n * safe defaults as `getComplianceContext()`.\n *\n * These are CLIENT-SIDE HEURISTICS, not authoritative geolocation, and do NOT\n * gate or alter fingerprint collection. Use `likelyRequiresConsent` together\n * with your own consent state to decide whether to collect a fingerprint —\n * obtaining consent where required (EU ePrivacy/GDPR, UK PECR, etc.) is the\n * merchant's responsibility.\n *\n * @example\n * ```typescript\n * import { useComplianceContext, useTraceTail } from '@tracetail/react';\n *\n * function Tracker({ hasConsent }: { hasConsent: boolean }) {\n * const compliance = useComplianceContext();\n * const shouldCollect = !compliance.likelyRequiresConsent || hasConsent;\n * const { fingerprint } = useTraceTail({ immediate: shouldCollect });\n * return shouldCollect ? <span>{fingerprint?.visitorId}</span> : null;\n * }\n * ```\n */\nexport function useComplianceContext(): ComplianceContext {\n // Empty dependency list: compute once and keep the same reference for the\n // component's lifetime. useMemo (rather than useState/useEffect) keeps the\n // value available on the very first render, including during SSR.\n return useMemo(() => getComplianceContext(), []);\n}\n\n// Re-export types and utilities from the base package\nexport type {\n FingerprintOptions,\n FingerprintResult,\n ComponentData,\n ComplianceContext,\n ComplianceRegion\n} from '@tracetail/js';\n\nexport { TraceTail, getComplianceContext } from '@tracetail/js';\n\n// React-specific utilities\ninterface TraceTailProviderProps {\n children: ReactNode;\n apiKey: string;\n options?: Partial<FingerprintOptions>;\n}\n\nexport const TraceTailProvider: FC<TraceTailProviderProps> = ({ children }) => {\n // This is a simple provider that could be extended with context\n // For now, it just renders children since hooks manage their own instances\n return <>{children}</>;\n};\n\n/**\n * Get the current React package version\n */\nexport const getVersion = (): string => '2.3.4';\n\n// Default export\nexport default {\n useTraceTail,\n useVisitorId,\n useComplianceContext,\n TraceTailProvider,\n getVersion\n};"],"names":["_jsx","_Fragment"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -134,6 +134,38 @@ function useVisitorId(options) {
|
|
|
134
134
|
refresh
|
|
135
135
|
};
|
|
136
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* React hook returning client-side privacy / region compliance signals.
|
|
139
|
+
*
|
|
140
|
+
* The context is computed ONCE on mount (the underlying signals — timezone,
|
|
141
|
+
* locale, GPC, DNT — do not change during a session) and memoized for the
|
|
142
|
+
* lifetime of the component. SSR-safe: during server render it returns the same
|
|
143
|
+
* safe defaults as `getComplianceContext()`.
|
|
144
|
+
*
|
|
145
|
+
* These are CLIENT-SIDE HEURISTICS, not authoritative geolocation, and do NOT
|
|
146
|
+
* gate or alter fingerprint collection. Use `likelyRequiresConsent` together
|
|
147
|
+
* with your own consent state to decide whether to collect a fingerprint —
|
|
148
|
+
* obtaining consent where required (EU ePrivacy/GDPR, UK PECR, etc.) is the
|
|
149
|
+
* merchant's responsibility.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* import { useComplianceContext, useTraceTail } from '@tracetail/react';
|
|
154
|
+
*
|
|
155
|
+
* function Tracker({ hasConsent }: { hasConsent: boolean }) {
|
|
156
|
+
* const compliance = useComplianceContext();
|
|
157
|
+
* const shouldCollect = !compliance.likelyRequiresConsent || hasConsent;
|
|
158
|
+
* const { fingerprint } = useTraceTail({ immediate: shouldCollect });
|
|
159
|
+
* return shouldCollect ? <span>{fingerprint?.visitorId}</span> : null;
|
|
160
|
+
* }
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
function useComplianceContext() {
|
|
164
|
+
// Empty dependency list: compute once and keep the same reference for the
|
|
165
|
+
// component's lifetime. useMemo (rather than useState/useEffect) keeps the
|
|
166
|
+
// value available on the very first render, including during SSR.
|
|
167
|
+
return react.useMemo(() => js.getComplianceContext(), []);
|
|
168
|
+
}
|
|
137
169
|
const TraceTailProvider = ({ children }) => {
|
|
138
170
|
// This is a simple provider that could be extended with context
|
|
139
171
|
// For now, it just renders children since hooks manage their own instances
|
|
@@ -147,6 +179,7 @@ const getVersion = () => '2.3.4';
|
|
|
147
179
|
var index = {
|
|
148
180
|
useTraceTail,
|
|
149
181
|
useVisitorId,
|
|
182
|
+
useComplianceContext,
|
|
150
183
|
TraceTailProvider,
|
|
151
184
|
getVersion
|
|
152
185
|
};
|
|
@@ -155,9 +188,14 @@ Object.defineProperty(exports, "TraceTail", {
|
|
|
155
188
|
enumerable: true,
|
|
156
189
|
get: function () { return js.TraceTail; }
|
|
157
190
|
});
|
|
191
|
+
Object.defineProperty(exports, "getComplianceContext", {
|
|
192
|
+
enumerable: true,
|
|
193
|
+
get: function () { return js.getComplianceContext; }
|
|
194
|
+
});
|
|
158
195
|
exports.TraceTailProvider = TraceTailProvider;
|
|
159
196
|
exports.default = index;
|
|
160
197
|
exports.getVersion = getVersion;
|
|
198
|
+
exports.useComplianceContext = useComplianceContext;
|
|
161
199
|
exports.useTraceTail = useTraceTail;
|
|
162
200
|
exports.useVisitorId = useVisitorId;
|
|
163
201
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @tracetail/react - React Hooks for Enterprise Browser Fingerprinting\n * Version: 2.3.4\n *\n * Over 99.5% accuracy browser fingerprinting with React hooks and server-side processing.\n * Perfect for fraud detection, user analytics, and security applications.\n */\n\nimport { useEffect, useState, useCallback, useRef } from 'react';\nimport type { FC, ReactNode } from 'react';\nimport { TraceTail, FingerprintOptions, FingerprintResult } from '@tracetail/js';\n\nexport interface UseTraceTailOptions extends FingerprintOptions {\n immediate?: boolean;\n suspense?: boolean;\n}\n\nexport interface UseTraceTailReturn {\n fingerprint: FingerprintResult | null;\n loading: boolean;\n error: Error | null;\n generate: () => Promise<FingerprintResult>;\n regenerate: () => Promise<FingerprintResult>;\n}\n\n\n/**\n * React hook for basic browser fingerprinting\n * \n * @example\n * ```typescript\n * import { useTraceTail } from '@tracetail/react';\n * \n * function MyComponent() {\n * const { fingerprint, loading, error } = useTraceTail({\n * apiKey: 'your-api-key',\n * immediate: true\n * });\n * \n * if (loading) return <div>Generating fingerprint...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return <div>Visitor ID: {fingerprint?.visitorId}</div>;\n * }\n * ```\n */\nexport function useTraceTail(options: UseTraceTailOptions): UseTraceTailReturn {\n const [fingerprint, setFingerprint] = useState<FingerprintResult | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n \n const traceTailRef = useRef<TraceTail | null>(null);\n \n // Initialize TraceTail instance\n useEffect(() => {\n if (!traceTailRef.current) {\n traceTailRef.current = new TraceTail(options);\n }\n }, [options.apiKey, options.endpoint]);\n\n const generate = useCallback(async (): Promise<FingerprintResult> => {\n if (!traceTailRef.current) {\n throw new Error('TraceTail not initialized');\n }\n\n setLoading(true);\n setError(null);\n\n try {\n const result = await traceTailRef.current.generateFingerprint({\n verbose: true\n });\n setFingerprint(result);\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Unknown error');\n setError(error);\n throw error;\n } finally {\n setLoading(false);\n }\n }, []);\n\n const regenerate = useCallback(async (): Promise<FingerprintResult> => {\n setFingerprint(null);\n return generate();\n }, [generate]);\n\n // Auto-generate on mount if immediate is true\n useEffect(() => {\n if (options.immediate && !fingerprint && !loading) {\n generate().catch(() => {\n // Error is already handled in generate function\n });\n }\n }, [options.immediate, fingerprint, loading, generate]);\n\n return {\n fingerprint,\n loading,\n error,\n generate,\n regenerate\n };\n}\n\n\n/**\n * React hook for visitor identification with persistent storage\n * \n * @example\n * ```typescript\n * import { useVisitorId } from '@tracetail/react';\n * \n * function UserTrackingComponent() {\n * const { visitorId, isReturningVisitor, loading } = useVisitorId({\n * apiKey: 'your-api-key',\n * storageKey: 'app_visitor_id'\n * });\n * \n * return (\n * <div>\n * <p>Visitor: {visitorId}</p>\n * <p>Status: {isReturningVisitor ? 'Returning' : 'New'} visitor</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useVisitorId(options: UseTraceTailOptions & {\n storageKey?: string;\n}): {\n visitorId: string | null;\n isReturningVisitor: boolean;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n} {\n const storageKey = options.storageKey || 'tracetail_visitor_id';\n const [visitorId, setVisitorId] = useState<string | null>(null);\n const [isReturningVisitor, setIsReturningVisitor] = useState(false);\n \n const { fingerprint, loading, error, generate } = useTraceTail({\n ...options,\n immediate: true\n });\n\n // Update visitor ID when fingerprint changes\n useEffect(() => {\n if (fingerprint?.visitorId) {\n const storedVisitorId = localStorage.getItem(storageKey);\n \n if (storedVisitorId) {\n setIsReturningVisitor(storedVisitorId === fingerprint.visitorId);\n } else {\n setIsReturningVisitor(false);\n }\n \n setVisitorId(fingerprint.visitorId);\n localStorage.setItem(storageKey, fingerprint.visitorId);\n }\n }, [fingerprint?.visitorId, storageKey]);\n\n const refresh = useCallback(async () => {\n await generate();\n }, [generate]);\n\n return {\n visitorId,\n isReturningVisitor,\n loading,\n error,\n refresh\n };\n}\n\n\n// Re-export types and utilities from the base package\nexport type {\n FingerprintOptions,\n FingerprintResult,\n ComponentData\n} from '@tracetail/js';\n\nexport { TraceTail } from '@tracetail/js';\n\n// React-specific utilities\ninterface TraceTailProviderProps {\n children: ReactNode;\n apiKey: string;\n options?: Partial<FingerprintOptions>;\n}\n\nexport const TraceTailProvider: FC<TraceTailProviderProps> = ({ children }) => {\n // This is a simple provider that could be extended with context\n // For now, it just renders children since hooks manage their own instances\n return <>{children}</>;\n};\n\n/**\n * Get the current React package version\n */\nexport const getVersion = (): string => '2.3.4';\n\n// Default export\nexport default {\n useTraceTail,\n useVisitorId,\n TraceTailProvider,\n getVersion\n};"],"names":["useState","useRef","useEffect","TraceTail","useCallback","_jsx","_Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @tracetail/react - React Hooks for Enterprise Browser Fingerprinting\n * Version: 2.3.4\n *\n * Over 99.5% accuracy browser fingerprinting with React hooks and server-side processing.\n * Perfect for fraud detection, user analytics, and security applications.\n */\n\nimport { useEffect, useState, useCallback, useRef, useMemo } from 'react';\nimport type { FC, ReactNode } from 'react';\nimport {\n TraceTail,\n FingerprintOptions,\n FingerprintResult,\n getComplianceContext,\n} from '@tracetail/js';\nimport type { ComplianceContext } from '@tracetail/js';\n\nexport interface UseTraceTailOptions extends FingerprintOptions {\n immediate?: boolean;\n suspense?: boolean;\n}\n\nexport interface UseTraceTailReturn {\n fingerprint: FingerprintResult | null;\n loading: boolean;\n error: Error | null;\n generate: () => Promise<FingerprintResult>;\n regenerate: () => Promise<FingerprintResult>;\n}\n\n\n/**\n * React hook for basic browser fingerprinting\n * \n * @example\n * ```typescript\n * import { useTraceTail } from '@tracetail/react';\n * \n * function MyComponent() {\n * const { fingerprint, loading, error } = useTraceTail({\n * apiKey: 'your-api-key',\n * immediate: true\n * });\n * \n * if (loading) return <div>Generating fingerprint...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return <div>Visitor ID: {fingerprint?.visitorId}</div>;\n * }\n * ```\n */\nexport function useTraceTail(options: UseTraceTailOptions): UseTraceTailReturn {\n const [fingerprint, setFingerprint] = useState<FingerprintResult | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n \n const traceTailRef = useRef<TraceTail | null>(null);\n \n // Initialize TraceTail instance\n useEffect(() => {\n if (!traceTailRef.current) {\n traceTailRef.current = new TraceTail(options);\n }\n }, [options.apiKey, options.endpoint]);\n\n const generate = useCallback(async (): Promise<FingerprintResult> => {\n if (!traceTailRef.current) {\n throw new Error('TraceTail not initialized');\n }\n\n setLoading(true);\n setError(null);\n\n try {\n const result = await traceTailRef.current.generateFingerprint({\n verbose: true\n });\n setFingerprint(result);\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Unknown error');\n setError(error);\n throw error;\n } finally {\n setLoading(false);\n }\n }, []);\n\n const regenerate = useCallback(async (): Promise<FingerprintResult> => {\n setFingerprint(null);\n return generate();\n }, [generate]);\n\n // Auto-generate on mount if immediate is true\n useEffect(() => {\n if (options.immediate && !fingerprint && !loading) {\n generate().catch(() => {\n // Error is already handled in generate function\n });\n }\n }, [options.immediate, fingerprint, loading, generate]);\n\n return {\n fingerprint,\n loading,\n error,\n generate,\n regenerate\n };\n}\n\n\n/**\n * React hook for visitor identification with persistent storage\n * \n * @example\n * ```typescript\n * import { useVisitorId } from '@tracetail/react';\n * \n * function UserTrackingComponent() {\n * const { visitorId, isReturningVisitor, loading } = useVisitorId({\n * apiKey: 'your-api-key',\n * storageKey: 'app_visitor_id'\n * });\n * \n * return (\n * <div>\n * <p>Visitor: {visitorId}</p>\n * <p>Status: {isReturningVisitor ? 'Returning' : 'New'} visitor</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useVisitorId(options: UseTraceTailOptions & {\n storageKey?: string;\n}): {\n visitorId: string | null;\n isReturningVisitor: boolean;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n} {\n const storageKey = options.storageKey || 'tracetail_visitor_id';\n const [visitorId, setVisitorId] = useState<string | null>(null);\n const [isReturningVisitor, setIsReturningVisitor] = useState(false);\n \n const { fingerprint, loading, error, generate } = useTraceTail({\n ...options,\n immediate: true\n });\n\n // Update visitor ID when fingerprint changes\n useEffect(() => {\n if (fingerprint?.visitorId) {\n const storedVisitorId = localStorage.getItem(storageKey);\n \n if (storedVisitorId) {\n setIsReturningVisitor(storedVisitorId === fingerprint.visitorId);\n } else {\n setIsReturningVisitor(false);\n }\n \n setVisitorId(fingerprint.visitorId);\n localStorage.setItem(storageKey, fingerprint.visitorId);\n }\n }, [fingerprint?.visitorId, storageKey]);\n\n const refresh = useCallback(async () => {\n await generate();\n }, [generate]);\n\n return {\n visitorId,\n isReturningVisitor,\n loading,\n error,\n refresh\n };\n}\n\n\n/**\n * React hook returning client-side privacy / region compliance signals.\n *\n * The context is computed ONCE on mount (the underlying signals — timezone,\n * locale, GPC, DNT — do not change during a session) and memoized for the\n * lifetime of the component. SSR-safe: during server render it returns the same\n * safe defaults as `getComplianceContext()`.\n *\n * These are CLIENT-SIDE HEURISTICS, not authoritative geolocation, and do NOT\n * gate or alter fingerprint collection. Use `likelyRequiresConsent` together\n * with your own consent state to decide whether to collect a fingerprint —\n * obtaining consent where required (EU ePrivacy/GDPR, UK PECR, etc.) is the\n * merchant's responsibility.\n *\n * @example\n * ```typescript\n * import { useComplianceContext, useTraceTail } from '@tracetail/react';\n *\n * function Tracker({ hasConsent }: { hasConsent: boolean }) {\n * const compliance = useComplianceContext();\n * const shouldCollect = !compliance.likelyRequiresConsent || hasConsent;\n * const { fingerprint } = useTraceTail({ immediate: shouldCollect });\n * return shouldCollect ? <span>{fingerprint?.visitorId}</span> : null;\n * }\n * ```\n */\nexport function useComplianceContext(): ComplianceContext {\n // Empty dependency list: compute once and keep the same reference for the\n // component's lifetime. useMemo (rather than useState/useEffect) keeps the\n // value available on the very first render, including during SSR.\n return useMemo(() => getComplianceContext(), []);\n}\n\n// Re-export types and utilities from the base package\nexport type {\n FingerprintOptions,\n FingerprintResult,\n ComponentData,\n ComplianceContext,\n ComplianceRegion\n} from '@tracetail/js';\n\nexport { TraceTail, getComplianceContext } from '@tracetail/js';\n\n// React-specific utilities\ninterface TraceTailProviderProps {\n children: ReactNode;\n apiKey: string;\n options?: Partial<FingerprintOptions>;\n}\n\nexport const TraceTailProvider: FC<TraceTailProviderProps> = ({ children }) => {\n // This is a simple provider that could be extended with context\n // For now, it just renders children since hooks manage their own instances\n return <>{children}</>;\n};\n\n/**\n * Get the current React package version\n */\nexport const getVersion = (): string => '2.3.4';\n\n// Default export\nexport default {\n useTraceTail,\n useVisitorId,\n useComplianceContext,\n TraceTailProvider,\n getVersion\n};"],"names":["useState","useRef","useEffect","TraceTail","useCallback","useMemo","getComplianceContext","_jsx","_Fragment"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tracetail/react",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.15",
|
|
4
4
|
"description": "React hooks for TraceTail enterprise browser fingerprinting with over 99.5% accuracy. TypeScript support and React 18 compatibility.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"react": ">=16.8.0"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@tracetail/js": "^2.3.
|
|
55
|
+
"@tracetail/js": "^2.3.15"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@rollup/plugin-typescript": "^11.1.6",
|