humanbehavior-js 0.4.16 → 0.4.18
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/cjs/wizard/index.cjs +6 -8
- package/dist/cjs/wizard/index.cjs.map +1 -1
- package/dist/cli/ai-auto-install.js +6 -8
- package/dist/cli/ai-auto-install.js.map +1 -1
- package/dist/esm/wizard/index.js +6 -8
- package/dist/esm/wizard/index.js.map +1 -1
- package/package/WIZARD_USAGE_GUIDE.md +381 -0
- package/package/canvas-recording-demo.html +143 -0
- package/package/clean-console-demo.html +39 -0
- package/package/dist/cjs/angular/index.cjs +14354 -0
- package/package/dist/cjs/angular/index.cjs.map +1 -0
- package/package/dist/cjs/index.cjs +14323 -0
- package/package/dist/cjs/index.cjs.map +1 -0
- package/package/dist/cjs/install-wizard.cjs +1530 -0
- package/package/dist/cjs/install-wizard.cjs.map +1 -0
- package/package/dist/cjs/react/index.cjs +14478 -0
- package/package/dist/cjs/react/index.cjs.map +1 -0
- package/package/dist/cjs/remix/index.cjs +14452 -0
- package/package/dist/cjs/remix/index.cjs.map +1 -0
- package/package/dist/cjs/svelte/index.cjs +14308 -0
- package/package/dist/cjs/svelte/index.cjs.map +1 -0
- package/package/dist/cjs/vue/index.cjs +14317 -0
- package/package/dist/cjs/vue/index.cjs.map +1 -0
- package/package/dist/cjs/wizard/index.cjs +3446 -0
- package/package/dist/cjs/wizard/index.cjs.map +1 -0
- package/package/dist/cli/ai-auto-install.cjs +57161 -0
- package/package/dist/cli/ai-auto-install.cjs.map +1 -0
- package/package/dist/cli/ai-auto-install.js +1969 -0
- package/package/dist/cli/ai-auto-install.js.map +1 -0
- package/package/dist/cli/auto-install.cjs +56352 -0
- package/package/dist/cli/auto-install.cjs.map +1 -0
- package/package/dist/cli/auto-install.js +1957 -0
- package/package/dist/cli/auto-install.js.map +1 -0
- package/package/dist/esm/angular/index.js +14350 -0
- package/package/dist/esm/angular/index.js.map +1 -0
- package/package/dist/esm/index.js +14309 -0
- package/package/dist/esm/index.js.map +1 -0
- package/package/dist/esm/install-wizard.js +1507 -0
- package/package/dist/esm/install-wizard.js.map +1 -0
- package/package/dist/esm/react/index.js +14472 -0
- package/package/dist/esm/react/index.js.map +1 -0
- package/package/dist/esm/remix/index.js +14448 -0
- package/package/dist/esm/remix/index.js.map +1 -0
- package/package/dist/esm/svelte/index.js +14306 -0
- package/package/dist/esm/svelte/index.js.map +1 -0
- package/package/dist/esm/vue/index.js +14315 -0
- package/package/dist/esm/vue/index.js.map +1 -0
- package/package/dist/esm/wizard/index.js +3415 -0
- package/package/dist/esm/wizard/index.js.map +1 -0
- package/package/dist/index.min.js +2 -0
- package/package/dist/index.min.js.map +1 -0
- package/package/dist/types/angular/index.d.ts +267 -0
- package/package/dist/types/index.d.ts +373 -0
- package/package/dist/types/install-wizard.d.ts +156 -0
- package/package/dist/types/react/index.d.ts +255 -0
- package/package/dist/types/remix/index.d.ts +246 -0
- package/package/dist/types/svelte/index.d.ts +232 -0
- package/package/dist/types/vue/index.d.ts +15 -0
- package/package/dist/types/wizard/index.d.ts +523 -0
- package/package/package.json +105 -0
- package/package/readme.md +281 -0
- package/package/rollup.config.js +422 -0
- package/package/simple-demo.html +26 -0
- package/package/simple-spa.html +838 -0
- package/package/src/angular/index.ts +79 -0
- package/package/src/api.ts +376 -0
- package/package/src/index.ts +28 -0
- package/package/src/react/AutoInstallWizard.tsx +557 -0
- package/package/src/react/browser.ts +8 -0
- package/package/src/react/index.tsx +308 -0
- package/package/src/redact.ts +521 -0
- package/package/src/remix/index.ts +16 -0
- package/package/src/svelte/index.ts +14 -0
- package/package/src/tracker.ts +1319 -0
- package/package/src/types/clack.d.ts +31 -0
- package/package/src/utils/logger.ts +144 -0
- package/package/src/vue/index.ts +29 -0
- package/package/src/wizard/README.md +114 -0
- package/package/src/wizard/ai/ai-install-wizard.ts +897 -0
- package/package/src/wizard/ai/manual-framework-wizard.ts +238 -0
- package/package/src/wizard/cli/ai-auto-install.ts +243 -0
- package/package/src/wizard/cli/auto-install.ts +224 -0
- package/package/src/wizard/core/install-wizard.ts +1744 -0
- package/package/src/wizard/index.ts +23 -0
- package/package/src/wizard/services/centralized-ai-service.ts +668 -0
- package/package/src/wizard/services/remote-ai-service.ts +240 -0
- package/package/tsconfig.json +24 -0
- package/package.json +1 -1
- package/src/wizard/cli/ai-auto-install.ts +4 -6
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import React, { useEffect, useState, createContext, useContext, ReactNode, useCallback, useMemo, useRef } from "react";
|
|
2
|
+
import { HumanBehaviorTracker, logError, logWarn, logDebug } from "./browser";
|
|
3
|
+
|
|
4
|
+
// Check if we're in a browser environment
|
|
5
|
+
const isBrowser = () => typeof window !== 'undefined';
|
|
6
|
+
|
|
7
|
+
// Define the public interface that components will interact with
|
|
8
|
+
interface HumanBehaviorInterface {
|
|
9
|
+
addEvent: (event: any) => void;
|
|
10
|
+
identifyUser: ({ userProperties }: { userProperties: Record<string, any> }) => Promise<string>;
|
|
11
|
+
start: () => void;
|
|
12
|
+
stop: () => void;
|
|
13
|
+
logout: () => void;
|
|
14
|
+
viewLogs: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface HumanBehaviorContextType {
|
|
18
|
+
humanBehavior: HumanBehaviorTracker | null;
|
|
19
|
+
queueEvent: (event: any) => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface HumanBehaviorProviderProps {
|
|
23
|
+
// Either provide an apiKey to create a new client, or provide an existing client
|
|
24
|
+
apiKey?: string;
|
|
25
|
+
client?: HumanBehaviorTracker;
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
options?: {
|
|
28
|
+
ingestionUrl?: string;
|
|
29
|
+
logLevel?: 'none' | 'error' | 'warn' | 'info' | 'debug';
|
|
30
|
+
redactFields?: string[];
|
|
31
|
+
suppressConsoleErrors?: boolean;
|
|
32
|
+
recordCanvas?: boolean; // Enable canvas recording with PostHog-style protection
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Default context to prevent unnecessary re-renders
|
|
37
|
+
const defaultContext: HumanBehaviorContextType = {
|
|
38
|
+
humanBehavior: null,
|
|
39
|
+
queueEvent: (event: any) => {
|
|
40
|
+
// In server-side, just no-op
|
|
41
|
+
if (typeof window === 'undefined') {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
logWarn('HumanBehavior not initialized yet, event queued:', event);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const HumanBehaviorContext = createContext<HumanBehaviorTracker | null>(null);
|
|
49
|
+
|
|
50
|
+
export const HumanBehaviorProvider = ({ apiKey, client, children, options }: HumanBehaviorProviderProps) => {
|
|
51
|
+
const [humanBehavior, setHumanBehavior] = useState<HumanBehaviorTracker | null>(client || null);
|
|
52
|
+
const [eventQueue, setEventQueue] = useState<any[]>([]);
|
|
53
|
+
const [isMounted, setIsMounted] = useState(false);
|
|
54
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
55
|
+
|
|
56
|
+
// Use refs to avoid dependency issues in useEffect
|
|
57
|
+
const apiKeyRef = useRef(apiKey);
|
|
58
|
+
const clientRef = useRef(client);
|
|
59
|
+
const eventQueueRef = useRef(eventQueue);
|
|
60
|
+
|
|
61
|
+
// Update refs when props change
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
apiKeyRef.current = apiKey;
|
|
64
|
+
clientRef.current = client;
|
|
65
|
+
}, [apiKey, client]);
|
|
66
|
+
|
|
67
|
+
// Update eventQueue ref when queue changes
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
eventQueueRef.current = eventQueue;
|
|
70
|
+
}, [eventQueue]);
|
|
71
|
+
|
|
72
|
+
// Memoized queueEvent function to prevent unnecessary re-renders
|
|
73
|
+
const queueEvent = useCallback((event: any) => {
|
|
74
|
+
setEventQueue(prev => [...prev, event]);
|
|
75
|
+
}, []);
|
|
76
|
+
|
|
77
|
+
// Handle mounting state
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
setIsMounted(true);
|
|
80
|
+
}, []);
|
|
81
|
+
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
// Only run in browser
|
|
84
|
+
if (!(isBrowser())) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Skip if not mounted yet (handles Next.js hydration)
|
|
89
|
+
if (!isMounted) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// If client is provided, use that
|
|
94
|
+
if (clientRef.current) {
|
|
95
|
+
setHumanBehavior(clientRef.current);
|
|
96
|
+
setIsInitialized(true);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// If no client is provided, apiKey is required
|
|
101
|
+
if (!apiKeyRef.current || apiKeyRef.current.trim() === '') {
|
|
102
|
+
logError("An apiKey is required when no client is provided");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (humanBehavior !== null) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Create new tracker instance with the validated apiKey and options
|
|
111
|
+
const tracker = HumanBehaviorTracker.init(
|
|
112
|
+
apiKeyRef.current.trim(),
|
|
113
|
+
{
|
|
114
|
+
ingestionUrl: options?.ingestionUrl,
|
|
115
|
+
logLevel: options?.logLevel,
|
|
116
|
+
redactFields: options?.redactFields,
|
|
117
|
+
suppressConsoleErrors: options?.suppressConsoleErrors,
|
|
118
|
+
recordCanvas: options?.recordCanvas, // Pass canvas recording option
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
setHumanBehavior(tracker);
|
|
123
|
+
|
|
124
|
+
// Wait for initialization to complete
|
|
125
|
+
tracker.initializationPromise?.then(async () => {
|
|
126
|
+
await tracker.start();
|
|
127
|
+
setIsInitialized(true);
|
|
128
|
+
|
|
129
|
+
// Process any queued events
|
|
130
|
+
const currentQueue = eventQueueRef.current;
|
|
131
|
+
if (currentQueue.length > 0) {
|
|
132
|
+
for (const event of currentQueue) {
|
|
133
|
+
if (event.type === 'identify') {
|
|
134
|
+
logDebug('Processing queued identify event', event);
|
|
135
|
+
try {
|
|
136
|
+
await tracker.identifyUser({ userProperties: event.userProperties });
|
|
137
|
+
} catch (error) {
|
|
138
|
+
logError('Failed to process queued user info:', error);
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
tracker.addEvent(event);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
setEventQueue([]); // Clear the queue
|
|
145
|
+
}
|
|
146
|
+
}).catch(error => {
|
|
147
|
+
logError('Failed to initialize HumanBehaviorTracker:', error);
|
|
148
|
+
});
|
|
149
|
+
}, [isMounted, humanBehavior]); // Removed apiKey, client, eventQueue from dependencies
|
|
150
|
+
|
|
151
|
+
// Memoized context value to prevent unnecessary re-renders
|
|
152
|
+
const contextValue = useMemo(() => {
|
|
153
|
+
if (!isMounted) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (!isInitialized) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return humanBehavior;
|
|
162
|
+
}, [isMounted, isInitialized, humanBehavior]);
|
|
163
|
+
|
|
164
|
+
// If not in browser, render children without context
|
|
165
|
+
if (!(isBrowser())) {
|
|
166
|
+
return <>{children}</>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<HumanBehaviorContext.Provider value={contextValue}>
|
|
171
|
+
<HumanBehaviorPageView />
|
|
172
|
+
{children}
|
|
173
|
+
</HumanBehaviorContext.Provider>
|
|
174
|
+
);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Default implementation for when tracker is not available
|
|
178
|
+
const defaultImplementation: HumanBehaviorInterface = {
|
|
179
|
+
addEvent: () => {},
|
|
180
|
+
identifyUser: async ({ userProperties }: { userProperties: Record<string, any> }) => {
|
|
181
|
+
return '';
|
|
182
|
+
},
|
|
183
|
+
start: () => {},
|
|
184
|
+
stop: () => {},
|
|
185
|
+
logout: () => {},
|
|
186
|
+
viewLogs: () => {},
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Memoized queuing implementation for initialization period
|
|
190
|
+
const createQueuingImplementation = (queueEvent: (event: any) => void): HumanBehaviorInterface => ({
|
|
191
|
+
addEvent: (event: any) => {
|
|
192
|
+
queueEvent(event);
|
|
193
|
+
},
|
|
194
|
+
identifyUser: async ({ userProperties }: { userProperties: Record<string, any> }) => {
|
|
195
|
+
queueEvent({
|
|
196
|
+
type: 'identify',
|
|
197
|
+
userProperties,
|
|
198
|
+
});
|
|
199
|
+
return ''; // Return empty string to match interface
|
|
200
|
+
},
|
|
201
|
+
start: () => {
|
|
202
|
+
// Start will be called automatically when initialized
|
|
203
|
+
},
|
|
204
|
+
stop: () => {
|
|
205
|
+
// Stop is a no-op when not initialized
|
|
206
|
+
},
|
|
207
|
+
logout: () => {
|
|
208
|
+
// Logout is a no-op when not initialized
|
|
209
|
+
},
|
|
210
|
+
viewLogs: () => {
|
|
211
|
+
logWarn('Logs are not available until HumanBehaviorTracker is initialized');
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
export const useHumanBehavior = () => {
|
|
216
|
+
const tracker = useContext(HumanBehaviorContext);
|
|
217
|
+
if (!tracker) {
|
|
218
|
+
throw new Error('useHumanBehavior must be used within a HumanBehaviorProvider');
|
|
219
|
+
}
|
|
220
|
+
return tracker;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
// Custom hook for managing redaction fields dynamically
|
|
224
|
+
export const useRedaction = () => {
|
|
225
|
+
const tracker = useHumanBehavior();
|
|
226
|
+
|
|
227
|
+
const setRedactedFields = useCallback((fields: string[]) => {
|
|
228
|
+
tracker.setRedactedFields(fields);
|
|
229
|
+
}, [tracker]);
|
|
230
|
+
|
|
231
|
+
const isRedactionActive = useCallback(() => {
|
|
232
|
+
return tracker.isRedactionActive();
|
|
233
|
+
}, [tracker]);
|
|
234
|
+
|
|
235
|
+
const getRedactedFields = useCallback(() => {
|
|
236
|
+
return tracker.getRedactedFields();
|
|
237
|
+
}, [tracker]);
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
setRedactedFields,
|
|
241
|
+
isRedactionActive,
|
|
242
|
+
getRedactedFields
|
|
243
|
+
};
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// Custom hook for managing user info
|
|
247
|
+
export const useUserTracking = () => {
|
|
248
|
+
const tracker = useHumanBehavior();
|
|
249
|
+
|
|
250
|
+
const identifyUser = useCallback(async ({ userProperties }: { userProperties: Record<string, any> }) => {
|
|
251
|
+
try {
|
|
252
|
+
await tracker.identifyUser({ userProperties });
|
|
253
|
+
return { success: true };
|
|
254
|
+
} catch (error) {
|
|
255
|
+
logError('Failed to identify user:', error);
|
|
256
|
+
return { success: false, error };
|
|
257
|
+
}
|
|
258
|
+
}, [tracker]);
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
identifyUser
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// Automatic page tracking component (similar to PostHog's PostHogPageView)
|
|
266
|
+
function HumanBehaviorPageView() {
|
|
267
|
+
const tracker = useContext(HumanBehaviorContext);
|
|
268
|
+
|
|
269
|
+
useEffect(() => {
|
|
270
|
+
if (tracker && typeof window !== 'undefined') {
|
|
271
|
+
// Track initial page load
|
|
272
|
+
tracker.trackPageView();
|
|
273
|
+
|
|
274
|
+
// Listen for route changes (for SPAs)
|
|
275
|
+
const handleRouteChange = () => {
|
|
276
|
+
tracker.trackPageView();
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// Listen for popstate (back/forward navigation)
|
|
280
|
+
window.addEventListener('popstate', handleRouteChange);
|
|
281
|
+
|
|
282
|
+
// Listen for pushstate/replacestate (programmatic navigation)
|
|
283
|
+
const originalPushState = history.pushState;
|
|
284
|
+
const originalReplaceState = history.replaceState;
|
|
285
|
+
|
|
286
|
+
history.pushState = function(...args) {
|
|
287
|
+
originalPushState.apply(this, args);
|
|
288
|
+
handleRouteChange();
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
history.replaceState = function(...args) {
|
|
292
|
+
originalReplaceState.apply(this, args);
|
|
293
|
+
handleRouteChange();
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
return () => {
|
|
297
|
+
window.removeEventListener('popstate', handleRouteChange);
|
|
298
|
+
history.pushState = originalPushState;
|
|
299
|
+
history.replaceState = originalReplaceState;
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
}, [tracker]);
|
|
303
|
+
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Export the tracker class for direct use
|
|
308
|
+
export { HumanBehaviorTracker };
|