@cxpinsight/react-native 0.2.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/LICENSE +21 -0
- package/README.md +131 -0
- package/babel.js +101 -0
- package/instrumented/Pressable.d.ts +2 -0
- package/instrumented/Pressable.js +2 -0
- package/instrumented/ScrollView.d.ts +2 -0
- package/instrumented/ScrollView.js +2 -0
- package/instrumented/TextInput.d.ts +2 -0
- package/instrumented/TextInput.js +2 -0
- package/instrumented/TouchableOpacity.d.ts +2 -0
- package/instrumented/TouchableOpacity.js +2 -0
- package/lib/CXPinsight.d.ts +113 -0
- package/lib/CXPinsight.d.ts.map +1 -0
- package/lib/CXPinsight.js +831 -0
- package/lib/CXPinsight.js.map +1 -0
- package/lib/CXPinsightProvider.d.ts +19 -0
- package/lib/CXPinsightProvider.d.ts.map +1 -0
- package/lib/CXPinsightProvider.js +382 -0
- package/lib/CXPinsightProvider.js.map +1 -0
- package/lib/core/autoScreenTracker.d.ts +20 -0
- package/lib/core/autoScreenTracker.d.ts.map +1 -0
- package/lib/core/autoScreenTracker.js +66 -0
- package/lib/core/autoScreenTracker.js.map +1 -0
- package/lib/core/deepLinkTracker.d.ts +17 -0
- package/lib/core/deepLinkTracker.d.ts.map +1 -0
- package/lib/core/deepLinkTracker.js +81 -0
- package/lib/core/deepLinkTracker.js.map +1 -0
- package/lib/core/deviceInfo.d.ts +14 -0
- package/lib/core/deviceInfo.d.ts.map +1 -0
- package/lib/core/deviceInfo.js +166 -0
- package/lib/core/deviceInfo.js.map +1 -0
- package/lib/core/eventQueue.d.ts +23 -0
- package/lib/core/eventQueue.d.ts.map +1 -0
- package/lib/core/eventQueue.js +240 -0
- package/lib/core/eventQueue.js.map +1 -0
- package/lib/core/lifecycle.d.ts +18 -0
- package/lib/core/lifecycle.d.ts.map +1 -0
- package/lib/core/lifecycle.js +127 -0
- package/lib/core/lifecycle.js.map +1 -0
- package/lib/core/mobileRecorder.d.ts +15 -0
- package/lib/core/mobileRecorder.d.ts.map +1 -0
- package/lib/core/mobileRecorder.js +231 -0
- package/lib/core/mobileRecorder.js.map +1 -0
- package/lib/core/network.d.ts +10 -0
- package/lib/core/network.d.ts.map +1 -0
- package/lib/core/network.js +74 -0
- package/lib/core/network.js.map +1 -0
- package/lib/core/networkCapture.d.ts +22 -0
- package/lib/core/networkCapture.d.ts.map +1 -0
- package/lib/core/networkCapture.js +100 -0
- package/lib/core/networkCapture.js.map +1 -0
- package/lib/core/scrollCapture.d.ts +48 -0
- package/lib/core/scrollCapture.d.ts.map +1 -0
- package/lib/core/scrollCapture.js +221 -0
- package/lib/core/scrollCapture.js.map +1 -0
- package/lib/core/session.d.ts +15 -0
- package/lib/core/session.d.ts.map +1 -0
- package/lib/core/session.js +157 -0
- package/lib/core/session.js.map +1 -0
- package/lib/core/storage.d.ts +11 -0
- package/lib/core/storage.d.ts.map +1 -0
- package/lib/core/storage.js +59 -0
- package/lib/core/storage.js.map +1 -0
- package/lib/core/triggerEngine.d.ts +56 -0
- package/lib/core/triggerEngine.d.ts.map +1 -0
- package/lib/core/triggerEngine.js +432 -0
- package/lib/core/triggerEngine.js.map +1 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +11 -0
- package/lib/index.js.map +1 -0
- package/lib/instrumented/Pressable.d.ts +9 -0
- package/lib/instrumented/Pressable.d.ts.map +1 -0
- package/lib/instrumented/Pressable.js +96 -0
- package/lib/instrumented/Pressable.js.map +1 -0
- package/lib/instrumented/ScrollView.d.ts +6 -0
- package/lib/instrumented/ScrollView.d.ts.map +1 -0
- package/lib/instrumented/ScrollView.js +101 -0
- package/lib/instrumented/ScrollView.js.map +1 -0
- package/lib/instrumented/TextInput.d.ts +9 -0
- package/lib/instrumented/TextInput.d.ts.map +1 -0
- package/lib/instrumented/TextInput.js +75 -0
- package/lib/instrumented/TextInput.js.map +1 -0
- package/lib/instrumented/TouchableOpacity.d.ts +11 -0
- package/lib/instrumented/TouchableOpacity.d.ts.map +1 -0
- package/lib/instrumented/TouchableOpacity.js +96 -0
- package/lib/instrumented/TouchableOpacity.js.map +1 -0
- package/lib/instrumented/index.d.ts +19 -0
- package/lib/instrumented/index.d.ts.map +1 -0
- package/lib/instrumented/index.js +28 -0
- package/lib/instrumented/index.js.map +1 -0
- package/lib/instrumented/interactionObserver.d.ts +29 -0
- package/lib/instrumented/interactionObserver.d.ts.map +1 -0
- package/lib/instrumented/interactionObserver.js +38 -0
- package/lib/instrumented/interactionObserver.js.map +1 -0
- package/lib/setup/AccessibilityScanner.d.ts +32 -0
- package/lib/setup/AccessibilityScanner.d.ts.map +1 -0
- package/lib/setup/AccessibilityScanner.js +127 -0
- package/lib/setup/AccessibilityScanner.js.map +1 -0
- package/lib/setup/ElementIdentifier.d.ts +65 -0
- package/lib/setup/ElementIdentifier.d.ts.map +1 -0
- package/lib/setup/ElementIdentifier.js +114 -0
- package/lib/setup/ElementIdentifier.js.map +1 -0
- package/lib/setup/ElementRegistry.d.ts +22 -0
- package/lib/setup/ElementRegistry.d.ts.map +1 -0
- package/lib/setup/ElementRegistry.js +47 -0
- package/lib/setup/ElementRegistry.js.map +1 -0
- package/lib/setup/SetupCodeEntry.d.ts +15 -0
- package/lib/setup/SetupCodeEntry.d.ts.map +1 -0
- package/lib/setup/SetupCodeEntry.js +198 -0
- package/lib/setup/SetupCodeEntry.js.map +1 -0
- package/lib/setup/SetupController.d.ts +29 -0
- package/lib/setup/SetupController.d.ts.map +1 -0
- package/lib/setup/SetupController.js +189 -0
- package/lib/setup/SetupController.js.map +1 -0
- package/lib/setup/SetupOverlay.d.ts +10 -0
- package/lib/setup/SetupOverlay.d.ts.map +1 -0
- package/lib/setup/SetupOverlay.js +408 -0
- package/lib/setup/SetupOverlay.js.map +1 -0
- package/lib/setup/TapInterceptor.d.ts +19 -0
- package/lib/setup/TapInterceptor.d.ts.map +1 -0
- package/lib/setup/TapInterceptor.js +98 -0
- package/lib/setup/TapInterceptor.js.map +1 -0
- package/lib/setup/TouchObserver.d.ts +25 -0
- package/lib/setup/TouchObserver.d.ts.map +1 -0
- package/lib/setup/TouchObserver.js +88 -0
- package/lib/setup/TouchObserver.js.map +1 -0
- package/lib/setup/TouchPatcher.d.ts +27 -0
- package/lib/setup/TouchPatcher.d.ts.map +1 -0
- package/lib/setup/TouchPatcher.js +182 -0
- package/lib/setup/TouchPatcher.js.map +1 -0
- package/lib/setup/index.d.ts +13 -0
- package/lib/setup/index.d.ts.map +1 -0
- package/lib/setup/index.js +45 -0
- package/lib/setup/index.js.map +1 -0
- package/lib/setup/useCXPElement.d.ts +25 -0
- package/lib/setup/useCXPElement.d.ts.map +1 -0
- package/lib/setup/useCXPElement.js +33 -0
- package/lib/setup/useCXPElement.js.map +1 -0
- package/lib/survey/SurveyModal.d.ts +10 -0
- package/lib/survey/SurveyModal.d.ts.map +1 -0
- package/lib/survey/SurveyModal.js +1650 -0
- package/lib/survey/SurveyModal.js.map +1 -0
- package/lib/survey/expressionEval.d.ts +10 -0
- package/lib/survey/expressionEval.d.ts.map +1 -0
- package/lib/survey/expressionEval.js +287 -0
- package/lib/survey/expressionEval.js.map +1 -0
- package/lib/survey/frequencyCap.d.ts +15 -0
- package/lib/survey/frequencyCap.d.ts.map +1 -0
- package/lib/survey/frequencyCap.js +116 -0
- package/lib/survey/frequencyCap.js.map +1 -0
- package/lib/survey/handsFreeVoice.d.ts +30 -0
- package/lib/survey/handsFreeVoice.d.ts.map +1 -0
- package/lib/survey/handsFreeVoice.js +312 -0
- package/lib/survey/handsFreeVoice.js.map +1 -0
- package/lib/survey/interpolate.d.ts +6 -0
- package/lib/survey/interpolate.d.ts.map +1 -0
- package/lib/survey/interpolate.js +61 -0
- package/lib/survey/interpolate.js.map +1 -0
- package/lib/survey/pagesFromV1.d.ts +6 -0
- package/lib/survey/pagesFromV1.d.ts.map +1 -0
- package/lib/survey/pagesFromV1.js +83 -0
- package/lib/survey/pagesFromV1.js.map +1 -0
- package/lib/survey/questions/CSATQuestion.d.ts +16 -0
- package/lib/survey/questions/CSATQuestion.d.ts.map +1 -0
- package/lib/survey/questions/CSATQuestion.js +37 -0
- package/lib/survey/questions/CSATQuestion.js.map +1 -0
- package/lib/survey/questions/DateQuestion.d.ts +20 -0
- package/lib/survey/questions/DateQuestion.d.ts.map +1 -0
- package/lib/survey/questions/DateQuestion.js +103 -0
- package/lib/survey/questions/DateQuestion.js.map +1 -0
- package/lib/survey/questions/ImagePickerQuestion.d.ts +33 -0
- package/lib/survey/questions/ImagePickerQuestion.d.ts.map +1 -0
- package/lib/survey/questions/ImagePickerQuestion.js +68 -0
- package/lib/survey/questions/ImagePickerQuestion.js.map +1 -0
- package/lib/survey/questions/ImageQuestion.d.ts +26 -0
- package/lib/survey/questions/ImageQuestion.d.ts.map +1 -0
- package/lib/survey/questions/ImageQuestion.js +24 -0
- package/lib/survey/questions/ImageQuestion.js.map +1 -0
- package/lib/survey/questions/MatrixCell.d.ts +45 -0
- package/lib/survey/questions/MatrixCell.d.ts.map +1 -0
- package/lib/survey/questions/MatrixCell.js +54 -0
- package/lib/survey/questions/MatrixCell.js.map +1 -0
- package/lib/survey/questions/MatrixDropdownQuestion.d.ts +29 -0
- package/lib/survey/questions/MatrixDropdownQuestion.d.ts.map +1 -0
- package/lib/survey/questions/MatrixDropdownQuestion.js +42 -0
- package/lib/survey/questions/MatrixDropdownQuestion.js.map +1 -0
- package/lib/survey/questions/MatrixDynamicQuestion.d.ts +26 -0
- package/lib/survey/questions/MatrixDynamicQuestion.d.ts.map +1 -0
- package/lib/survey/questions/MatrixDynamicQuestion.js +52 -0
- package/lib/survey/questions/MatrixDynamicQuestion.js.map +1 -0
- package/lib/survey/questions/MatrixQuestion.d.ts +38 -0
- package/lib/survey/questions/MatrixQuestion.d.ts.map +1 -0
- package/lib/survey/questions/MatrixQuestion.js +64 -0
- package/lib/survey/questions/MatrixQuestion.js.map +1 -0
- package/lib/survey/questions/MultiTextQuestion.d.ts +19 -0
- package/lib/survey/questions/MultiTextQuestion.d.ts.map +1 -0
- package/lib/survey/questions/MultiTextQuestion.js +64 -0
- package/lib/survey/questions/MultiTextQuestion.js.map +1 -0
- package/lib/survey/questions/MultipleChoiceQuestion.d.ts +25 -0
- package/lib/survey/questions/MultipleChoiceQuestion.d.ts.map +1 -0
- package/lib/survey/questions/MultipleChoiceQuestion.js +111 -0
- package/lib/survey/questions/MultipleChoiceQuestion.js.map +1 -0
- package/lib/survey/questions/NPSQuestion.d.ts +18 -0
- package/lib/survey/questions/NPSQuestion.d.ts.map +1 -0
- package/lib/survey/questions/NPSQuestion.js +62 -0
- package/lib/survey/questions/NPSQuestion.js.map +1 -0
- package/lib/survey/questions/PanelDynamicQuestion.d.ts +50 -0
- package/lib/survey/questions/PanelDynamicQuestion.d.ts.map +1 -0
- package/lib/survey/questions/PanelDynamicQuestion.js +62 -0
- package/lib/survey/questions/PanelDynamicQuestion.js.map +1 -0
- package/lib/survey/questions/RankingQuestion.d.ts +34 -0
- package/lib/survey/questions/RankingQuestion.d.ts.map +1 -0
- package/lib/survey/questions/RankingQuestion.js +85 -0
- package/lib/survey/questions/RankingQuestion.js.map +1 -0
- package/lib/survey/questions/RatingQuestion.d.ts +20 -0
- package/lib/survey/questions/RatingQuestion.d.ts.map +1 -0
- package/lib/survey/questions/RatingQuestion.js +53 -0
- package/lib/survey/questions/RatingQuestion.js.map +1 -0
- package/lib/survey/questions/TextQuestion.d.ts +17 -0
- package/lib/survey/questions/TextQuestion.d.ts.map +1 -0
- package/lib/survey/questions/TextQuestion.js +46 -0
- package/lib/survey/questions/TextQuestion.js.map +1 -0
- package/lib/survey/styleContract.d.ts +230 -0
- package/lib/survey/styleContract.d.ts.map +1 -0
- package/lib/survey/styleContract.js +365 -0
- package/lib/survey/styleContract.js.map +1 -0
- package/lib/survey/themePalette.d.ts +56 -0
- package/lib/survey/themePalette.d.ts.map +1 -0
- package/lib/survey/themePalette.js +63 -0
- package/lib/survey/themePalette.js.map +1 -0
- package/lib/survey/translationLookup.d.ts +4 -0
- package/lib/survey/translationLookup.d.ts.map +1 -0
- package/lib/survey/translationLookup.js +62 -0
- package/lib/survey/translationLookup.js.map +1 -0
- package/lib/survey/validate.d.ts +3 -0
- package/lib/survey/validate.d.ts.map +1 -0
- package/lib/survey/validate.js +159 -0
- package/lib/survey/validate.js.map +1 -0
- package/lib/survey/variablesResolver.d.ts +10 -0
- package/lib/survey/variablesResolver.d.ts.map +1 -0
- package/lib/survey/variablesResolver.js +107 -0
- package/lib/survey/variablesResolver.js.map +1 -0
- package/lib/survey/voiceParsers.d.ts +47 -0
- package/lib/survey/voiceParsers.d.ts.map +1 -0
- package/lib/survey/voiceParsers.js +310 -0
- package/lib/survey/voiceParsers.js.map +1 -0
- package/lib/types.d.ts +349 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +20 -0
- package/lib/types.js.map +1 -0
- package/metro.js +55 -0
- package/package.json +78 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.startLifecycleTracking = startLifecycleTracking;
|
|
37
|
+
exports.stopLifecycleTracking = stopLifecycleTracking;
|
|
38
|
+
exports.incrementEventCount = incrementEventCount;
|
|
39
|
+
const react_native_1 = require("react-native");
|
|
40
|
+
const storage = __importStar(require("./storage"));
|
|
41
|
+
const deviceInfo_1 = require("./deviceInfo");
|
|
42
|
+
const APP_VERSION_KEY = '@cxpinsight:appVersion';
|
|
43
|
+
const APP_OPEN_COUNT_KEY = '@cxpinsight:appOpenCount';
|
|
44
|
+
let listener = null;
|
|
45
|
+
let subscription = null;
|
|
46
|
+
let lastBackgroundedAt = null;
|
|
47
|
+
let sessionEventCount = 0;
|
|
48
|
+
let debugMode = false;
|
|
49
|
+
function log(...args) {
|
|
50
|
+
if (debugMode)
|
|
51
|
+
console.log('[CXPinsight:Lifecycle]', ...args);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Start lifecycle tracking. Call once during SDK init.
|
|
55
|
+
* Emits app_opened, app_installed, app_updated immediately,
|
|
56
|
+
* then listens for foreground/background transitions.
|
|
57
|
+
*/
|
|
58
|
+
async function startLifecycleTracking(onEvent, debug) {
|
|
59
|
+
debugMode = debug ?? false;
|
|
60
|
+
listener = onEvent;
|
|
61
|
+
sessionEventCount = 0;
|
|
62
|
+
const device = (0, deviceInfo_1.getDeviceInfo)();
|
|
63
|
+
const currentVersion = device.appVersion;
|
|
64
|
+
// Check install vs update
|
|
65
|
+
const savedVersion = await storage.get(APP_VERSION_KEY);
|
|
66
|
+
const openCount = ((await storage.get(APP_OPEN_COUNT_KEY)) ?? 0) + 1;
|
|
67
|
+
await storage.set(APP_OPEN_COUNT_KEY, openCount);
|
|
68
|
+
if (!savedVersion) {
|
|
69
|
+
// First ever launch
|
|
70
|
+
await storage.set(APP_VERSION_KEY, currentVersion);
|
|
71
|
+
emit('app_installed', { app_version: currentVersion });
|
|
72
|
+
log('App installed, version:', currentVersion);
|
|
73
|
+
}
|
|
74
|
+
else if (savedVersion !== currentVersion) {
|
|
75
|
+
// Version changed
|
|
76
|
+
await storage.set(APP_VERSION_KEY, currentVersion);
|
|
77
|
+
emit('app_updated', {
|
|
78
|
+
previous_version: savedVersion,
|
|
79
|
+
new_version: currentVersion,
|
|
80
|
+
});
|
|
81
|
+
log('App updated:', savedVersion, '→', currentVersion);
|
|
82
|
+
}
|
|
83
|
+
// App opened (cold start)
|
|
84
|
+
emit('app_opened', {
|
|
85
|
+
from_background: false,
|
|
86
|
+
app_open_count: openCount,
|
|
87
|
+
});
|
|
88
|
+
log('App opened, total opens:', openCount);
|
|
89
|
+
// Listen for foreground/background transitions
|
|
90
|
+
subscription?.remove();
|
|
91
|
+
subscription = react_native_1.AppState.addEventListener('change', handleAppStateChange);
|
|
92
|
+
}
|
|
93
|
+
/** Stop lifecycle tracking */
|
|
94
|
+
function stopLifecycleTracking() {
|
|
95
|
+
subscription?.remove();
|
|
96
|
+
subscription = null;
|
|
97
|
+
listener = null;
|
|
98
|
+
}
|
|
99
|
+
/** Increment the session event count (called by CXPinsight.track) */
|
|
100
|
+
function incrementEventCount() {
|
|
101
|
+
sessionEventCount++;
|
|
102
|
+
}
|
|
103
|
+
function handleAppStateChange(state) {
|
|
104
|
+
if (state === 'active') {
|
|
105
|
+
// App came to foreground
|
|
106
|
+
const now = Date.now();
|
|
107
|
+
const backgroundDuration = lastBackgroundedAt ? now - lastBackgroundedAt : 0;
|
|
108
|
+
lastBackgroundedAt = null;
|
|
109
|
+
emit('app_foregrounded', {
|
|
110
|
+
from_background: true,
|
|
111
|
+
background_duration_ms: backgroundDuration,
|
|
112
|
+
});
|
|
113
|
+
log('App foregrounded, background duration:', backgroundDuration, 'ms');
|
|
114
|
+
}
|
|
115
|
+
else if (state === 'background') {
|
|
116
|
+
// App going to background
|
|
117
|
+
lastBackgroundedAt = Date.now();
|
|
118
|
+
emit('app_backgrounded', {
|
|
119
|
+
event_count_this_session: sessionEventCount,
|
|
120
|
+
});
|
|
121
|
+
log('App backgrounded, events this session:', sessionEventCount);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function emit(type, data) {
|
|
125
|
+
listener?.({ type, data });
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/core/lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare function isRecording(): boolean;
|
|
2
|
+
export declare function startRecording(opts: {
|
|
3
|
+
sessionId: string;
|
|
4
|
+
userId: string;
|
|
5
|
+
applicationId?: string;
|
|
6
|
+
sampleRate?: number;
|
|
7
|
+
screen?: string | null;
|
|
8
|
+
maskInputs?: boolean;
|
|
9
|
+
captureScreen?: (() => Promise<string | null | undefined>) | null;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
export declare function recordFrame(kind: string, data?: Record<string, unknown>): void;
|
|
12
|
+
export declare function recordScreen(screen: string, previousScreen?: string | null): void;
|
|
13
|
+
export declare function recordTap(x: number, y: number, holdMs?: number): void;
|
|
14
|
+
export declare function stopRecording(): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=mobileRecorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mobileRecorder.d.ts","sourceRoot":"","sources":["../../src/core/mobileRecorder.ts"],"names":[],"mappings":"AA6DA,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAyCD,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC;CACnE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DhB;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAI9E;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAIjF;AAKD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,IAAI,CAOhE;AA0BD,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAanD"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isRecording = isRecording;
|
|
4
|
+
exports.startRecording = startRecording;
|
|
5
|
+
exports.recordFrame = recordFrame;
|
|
6
|
+
exports.recordScreen = recordScreen;
|
|
7
|
+
exports.recordTap = recordTap;
|
|
8
|
+
exports.stopRecording = stopRecording;
|
|
9
|
+
/**
|
|
10
|
+
* Mobile session recorder (timeline replay).
|
|
11
|
+
*
|
|
12
|
+
* rrweb replay is web-only (it serializes the DOM), so mobile can't reuse it.
|
|
13
|
+
* Instead this records a lightweight, privacy-safe *timeline* of the session —
|
|
14
|
+
* screen views, tracked events, and raw interactions (taps / focus / value
|
|
15
|
+
* changes) with their timestamps and target labels — and ships it through the
|
|
16
|
+
* SAME recording pipeline as web (/api/recordings/start|chunk|stop). Recordings
|
|
17
|
+
* scope to the applicationId sent on every SDK request, so mobile recordings
|
|
18
|
+
* live under the same application as the app's events. A player reconstructs the session as a
|
|
19
|
+
* step-by-step timeline (not pixel video).
|
|
20
|
+
*
|
|
21
|
+
* Never records entered text: value_change frames store a masked placeholder.
|
|
22
|
+
*/
|
|
23
|
+
const network_1 = require("./network");
|
|
24
|
+
const interactionObserver_1 = require("../instrumented/interactionObserver");
|
|
25
|
+
const FLUSH_EVERY = 25; // frames
|
|
26
|
+
const FLUSH_INTERVAL_MS = 10000; // ms
|
|
27
|
+
let recordingId = null;
|
|
28
|
+
let startTs = 0;
|
|
29
|
+
let buffer = [];
|
|
30
|
+
let flushTimer = null;
|
|
31
|
+
let unsubscribeInteractions = null;
|
|
32
|
+
let currentScreen = null;
|
|
33
|
+
let maskInputs = true;
|
|
34
|
+
// Optional screenshot capturer, injected via startRecording (from init config). When
|
|
35
|
+
// present (e.g. react-native-view-shot's captureScreen), we snapshot the screen so the
|
|
36
|
+
// replay can show the actual UI. Absent → timeline-only. Kept as injection (not a hard
|
|
37
|
+
// dependency) so apps that don't want screenshots don't need the native module.
|
|
38
|
+
let screenshotProvider = null;
|
|
39
|
+
const SHOT_MIN_INTERVAL_MS = 1000; // throttle: at most ~1 screenshot/sec
|
|
40
|
+
let lastShotAt = 0;
|
|
41
|
+
/** Best-effort screenshot → a 'screenshot' frame (base64 jpg). Deferred so the new
|
|
42
|
+
* screen has painted before we snapshot it. Throttled to bound size/bandwidth. */
|
|
43
|
+
function captureShot(reason) {
|
|
44
|
+
if (!recordingId || !screenshotProvider)
|
|
45
|
+
return;
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
if (now - lastShotAt < SHOT_MIN_INTERVAL_MS)
|
|
48
|
+
return;
|
|
49
|
+
lastShotAt = now;
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
const provider = screenshotProvider;
|
|
52
|
+
if (!recordingId || !provider)
|
|
53
|
+
return;
|
|
54
|
+
Promise.resolve().then(() => provider())
|
|
55
|
+
.then((b64) => { if (recordingId && b64)
|
|
56
|
+
recordFrame('screenshot', { image: b64, format: 'jpg', reason }); })
|
|
57
|
+
.catch(() => { });
|
|
58
|
+
}, 350);
|
|
59
|
+
}
|
|
60
|
+
function isRecording() {
|
|
61
|
+
return recordingId !== null;
|
|
62
|
+
}
|
|
63
|
+
/** Read an optional label off an interaction without assuming its exact shape. */
|
|
64
|
+
function interactionLabel(e) {
|
|
65
|
+
const r = e;
|
|
66
|
+
const candidate = r.label ?? r.accessibilityLabel ?? r.testID ?? r.text ?? r.elementId;
|
|
67
|
+
return typeof candidate === 'string' ? candidate : null;
|
|
68
|
+
}
|
|
69
|
+
// Deterministic per-session sampling — same FNV-1a as the server's shared
|
|
70
|
+
// shouldSample (shared/models/settingsSchema.js). Duplicated here (rather than
|
|
71
|
+
// imported) because @cxpinsight/react-native must ship without a shared/ path.
|
|
72
|
+
// A session's verdict is stable across process restarts and matches what a
|
|
73
|
+
// server-side sanity check would return, so the drop-during-recording story
|
|
74
|
+
// is consistent.
|
|
75
|
+
function sampleRate01(v, fallback = 1) {
|
|
76
|
+
const n = typeof v === 'number' ? v : (typeof v === 'string' && v.length > 0 ? Number(v) : NaN);
|
|
77
|
+
if (Number.isFinite(n) && n >= 0 && n <= 1)
|
|
78
|
+
return n;
|
|
79
|
+
return fallback;
|
|
80
|
+
}
|
|
81
|
+
function shouldRecordSession(applicationId, sessionId, rate) {
|
|
82
|
+
const r = sampleRate01(rate, 1);
|
|
83
|
+
if (r >= 1)
|
|
84
|
+
return true;
|
|
85
|
+
if (r <= 0)
|
|
86
|
+
return false;
|
|
87
|
+
if (!sessionId)
|
|
88
|
+
return true;
|
|
89
|
+
let h = 0x811c9dc5 >>> 0;
|
|
90
|
+
const key = String(applicationId || '') + '|' + String(sessionId);
|
|
91
|
+
for (let i = 0; i < key.length; i++) {
|
|
92
|
+
h ^= key.charCodeAt(i);
|
|
93
|
+
h = Math.imul(h, 0x01000193) >>> 0;
|
|
94
|
+
}
|
|
95
|
+
return (h % 100) < Math.floor(r * 100);
|
|
96
|
+
}
|
|
97
|
+
// Sticky per session — cache the verdict so an init/rollover/manual-start
|
|
98
|
+
// combo inside the same session never flips the decision. A mid-session flip
|
|
99
|
+
// would leave a partial recording with no start marker (the replay UI can't
|
|
100
|
+
// render that), and it would also defeat the "one recording per session"
|
|
101
|
+
// invariant onSessionRollover enforces.
|
|
102
|
+
let sampledOutFor = null;
|
|
103
|
+
async function startRecording(opts) {
|
|
104
|
+
if (recordingId)
|
|
105
|
+
return;
|
|
106
|
+
if (!opts.sessionId || !opts.userId)
|
|
107
|
+
return;
|
|
108
|
+
// Sampling gate — decided ONCE per session, sticky. Missing sampleRate = 1
|
|
109
|
+
// (record everything), preserving prior behavior for callers that don't opt
|
|
110
|
+
// into sampling yet.
|
|
111
|
+
const rate = sampleRate01(opts.sampleRate, 1);
|
|
112
|
+
if (sampledOutFor !== opts.sessionId) {
|
|
113
|
+
const keep = shouldRecordSession(opts.applicationId, opts.sessionId, rate);
|
|
114
|
+
sampledOutFor = keep ? null : opts.sessionId;
|
|
115
|
+
}
|
|
116
|
+
if (sampledOutFor === opts.sessionId) {
|
|
117
|
+
// No capture, no upload — behaves exactly like recording.enabled=false for
|
|
118
|
+
// this session. Return silently; the caller doesn't need to distinguish
|
|
119
|
+
// "sampled out" from "already running" — both cases mean "nothing more to do".
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
maskInputs = opts.maskInputs !== false;
|
|
123
|
+
screenshotProvider = opts.captureScreen ?? null;
|
|
124
|
+
lastShotAt = 0;
|
|
125
|
+
currentScreen = opts.screen ?? null;
|
|
126
|
+
try {
|
|
127
|
+
const res = await (0, network_1.sdkFetch)('POST', '/api/engagement/recordings/start', {
|
|
128
|
+
sessionId: opts.sessionId,
|
|
129
|
+
userId: opts.userId,
|
|
130
|
+
metadata: { platform: 'mobile', format: 'mobile-timeline', screen: currentScreen },
|
|
131
|
+
privacy: { maskInputs },
|
|
132
|
+
});
|
|
133
|
+
const id = res.success && res.data ? (res.data.recordingId ?? null) : null;
|
|
134
|
+
if (!id)
|
|
135
|
+
return;
|
|
136
|
+
recordingId = id;
|
|
137
|
+
startTs = Date.now();
|
|
138
|
+
buffer = [];
|
|
139
|
+
// Capture raw interactions. The observer now fans out to multiple subscribers,
|
|
140
|
+
// so recording always receives taps/inputs even if setup or tracking is also
|
|
141
|
+
// listening (previously this silently captured nothing in that case).
|
|
142
|
+
unsubscribeInteractions = (0, interactionObserver_1.setInteractionListener)((e) => {
|
|
143
|
+
recordFrame('interaction', {
|
|
144
|
+
interaction: e.interactionType,
|
|
145
|
+
label: interactionLabel(e),
|
|
146
|
+
// Never persist entered text.
|
|
147
|
+
value: e.interactionType === 'value_change' ? (maskInputs ? '•••' : undefined) : undefined,
|
|
148
|
+
});
|
|
149
|
+
// A tap often changes the UI — snapshot it (throttled).
|
|
150
|
+
captureShot('interaction');
|
|
151
|
+
});
|
|
152
|
+
flushTimer = setInterval(() => { void flush(); }, FLUSH_INTERVAL_MS);
|
|
153
|
+
recordFrame('start', { screen: currentScreen });
|
|
154
|
+
captureShot('start');
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// Best-effort; a failed start just means no recording this session.
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function recordFrame(kind, data) {
|
|
161
|
+
if (!recordingId)
|
|
162
|
+
return;
|
|
163
|
+
buffer.push({ t: Date.now() - startTs, kind, ...(data ?? {}) });
|
|
164
|
+
if (buffer.length >= FLUSH_EVERY)
|
|
165
|
+
void flush();
|
|
166
|
+
}
|
|
167
|
+
function recordScreen(screen, previousScreen) {
|
|
168
|
+
currentScreen = screen;
|
|
169
|
+
recordFrame('screen', { screen, previousScreen: previousScreen ?? undefined });
|
|
170
|
+
captureShot('screen');
|
|
171
|
+
}
|
|
172
|
+
// Raw tap coordinates for EVERY touch (incl. taps on non-interactive areas / dead taps),
|
|
173
|
+
// captured at the app root. Rendered as a tap ripple on the replay (like web's cursor).
|
|
174
|
+
let lastTapAt = 0;
|
|
175
|
+
function recordTap(x, y, holdMs = 0) {
|
|
176
|
+
if (!recordingId)
|
|
177
|
+
return;
|
|
178
|
+
const now = Date.now();
|
|
179
|
+
if (now - lastTapAt < 40)
|
|
180
|
+
return; // de-dupe the same physical touch
|
|
181
|
+
lastTapAt = now;
|
|
182
|
+
// holdMs = press duration → the replay grows the ripple then freezes it while held.
|
|
183
|
+
recordFrame('tap', { x: Math.round(x), y: Math.round(y), holdMs: Math.round(holdMs) });
|
|
184
|
+
}
|
|
185
|
+
async function flush() {
|
|
186
|
+
if (!recordingId || buffer.length === 0)
|
|
187
|
+
return;
|
|
188
|
+
const events = buffer;
|
|
189
|
+
buffer = [];
|
|
190
|
+
try {
|
|
191
|
+
// sdkFetch RESOLVES with { success:false } on an HTTP or network error rather than
|
|
192
|
+
// throwing, so the catch below never ran and a failed chunk vanished with no signal
|
|
193
|
+
// at all — a silent hole in the replay. Check the result explicitly.
|
|
194
|
+
const res = await (0, network_1.sdkFetch)('POST', `/api/engagement/recordings/${recordingId}/chunk`, {
|
|
195
|
+
events,
|
|
196
|
+
startTime: events[0]?.t,
|
|
197
|
+
endTime: events[events.length - 1]?.t,
|
|
198
|
+
});
|
|
199
|
+
if (!res.success && (0, network_1.getConfig)()?.debug) {
|
|
200
|
+
console.warn(`[CXPinsight:Recorder] Dropped a ${events.length}-frame chunk — ${res.error ?? 'unknown error'}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
// Drop the chunk on failure; keep recording rather than blocking the app.
|
|
205
|
+
if ((0, network_1.getConfig)()?.debug)
|
|
206
|
+
console.warn('[CXPinsight:Recorder] Chunk upload threw:', err);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function stopRecording() {
|
|
210
|
+
if (!recordingId)
|
|
211
|
+
return;
|
|
212
|
+
const id = recordingId;
|
|
213
|
+
recordFrame('stop', {});
|
|
214
|
+
await flush();
|
|
215
|
+
if (unsubscribeInteractions) {
|
|
216
|
+
unsubscribeInteractions();
|
|
217
|
+
unsubscribeInteractions = null;
|
|
218
|
+
}
|
|
219
|
+
if (flushTimer) {
|
|
220
|
+
clearInterval(flushTimer);
|
|
221
|
+
flushTimer = null;
|
|
222
|
+
}
|
|
223
|
+
recordingId = null;
|
|
224
|
+
startTs = 0;
|
|
225
|
+
buffer = [];
|
|
226
|
+
try {
|
|
227
|
+
await (0, network_1.sdkFetch)('POST', `/api/engagement/recordings/${id}/stop`, {});
|
|
228
|
+
}
|
|
229
|
+
catch { /* ignore */ }
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=mobileRecorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mobileRecorder.js","sourceRoot":"","sources":["../../src/core/mobileRecorder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CXPinsightConfig, NetworkResponse } from '../types';
|
|
2
|
+
export declare function configureNetwork(cfg: CXPinsightConfig): void;
|
|
3
|
+
/**
|
|
4
|
+
* Make an authenticated SDK request.
|
|
5
|
+
* Uses x-cxp-api-key + x-cxp-application-id headers (no JWT).
|
|
6
|
+
*/
|
|
7
|
+
export declare function sdkFetch<T = unknown>(method: 'GET' | 'POST' | 'PUT' | 'DELETE', path: string, body?: unknown): Promise<NetworkResponse<T>>;
|
|
8
|
+
export declare function getConfig(): CXPinsightConfig | null;
|
|
9
|
+
export declare function resetNetwork(): void;
|
|
10
|
+
//# sourceMappingURL=network.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/core/network.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAKlE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAG5D;AAQD;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EACxC,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,EACzC,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAiD7B;AAED,wBAAgB,SAAS,IAAI,gBAAgB,GAAG,IAAI,CAEnD;AAED,wBAAgB,YAAY,IAAI,IAAI,CAGnC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.configureNetwork = configureNetwork;
|
|
4
|
+
exports.sdkFetch = sdkFetch;
|
|
5
|
+
exports.getConfig = getConfig;
|
|
6
|
+
exports.resetNetwork = resetNetwork;
|
|
7
|
+
let config = null;
|
|
8
|
+
let debugMode = false;
|
|
9
|
+
function configureNetwork(cfg) {
|
|
10
|
+
config = cfg;
|
|
11
|
+
debugMode = cfg.debug ?? false;
|
|
12
|
+
}
|
|
13
|
+
function log(...args) {
|
|
14
|
+
if (debugMode) {
|
|
15
|
+
console.log('[CXPinsight]', ...args);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Make an authenticated SDK request.
|
|
20
|
+
* Uses x-cxp-api-key + x-cxp-application-id headers (no JWT).
|
|
21
|
+
*/
|
|
22
|
+
async function sdkFetch(method, path, body) {
|
|
23
|
+
if (!config) {
|
|
24
|
+
return { success: false, error: 'SDK not initialized' };
|
|
25
|
+
}
|
|
26
|
+
const url = `${config.apiBase}${path}`;
|
|
27
|
+
const controller = new AbortController();
|
|
28
|
+
const timeout = setTimeout(() => controller.abort(), 30000);
|
|
29
|
+
try {
|
|
30
|
+
log(`${method} ${path}`);
|
|
31
|
+
const headers = {
|
|
32
|
+
'Content-Type': 'application/json',
|
|
33
|
+
'x-cxp-api-key': config.apiKey,
|
|
34
|
+
};
|
|
35
|
+
if (config.applicationId)
|
|
36
|
+
headers['x-cxp-application-id'] = config.applicationId;
|
|
37
|
+
// Dev-only: force a client IP for server-side geo enrichment (localhost/emulator
|
|
38
|
+
// has no public IP). Omit in production — the real IP is used automatically.
|
|
39
|
+
if (config.debugIp)
|
|
40
|
+
headers['x-cxp-debug-ip'] = config.debugIp;
|
|
41
|
+
const response = await fetch(url, {
|
|
42
|
+
method,
|
|
43
|
+
headers,
|
|
44
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
45
|
+
signal: controller.signal,
|
|
46
|
+
});
|
|
47
|
+
clearTimeout(timeout);
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
const errorText = await response.text().catch(() => 'Unknown error');
|
|
50
|
+
log(`Error ${response.status}: ${errorText}`);
|
|
51
|
+
return { success: false, error: `HTTP ${response.status}: ${errorText}` };
|
|
52
|
+
}
|
|
53
|
+
const contentType = response.headers.get('content-type');
|
|
54
|
+
if (contentType?.includes('application/json')) {
|
|
55
|
+
const data = (await response.json());
|
|
56
|
+
return { success: true, data };
|
|
57
|
+
}
|
|
58
|
+
return { success: true };
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
clearTimeout(timeout);
|
|
62
|
+
const message = err instanceof Error ? err.message : 'Network error';
|
|
63
|
+
log(`Fetch error: ${message}`);
|
|
64
|
+
return { success: false, error: message };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function getConfig() {
|
|
68
|
+
return config;
|
|
69
|
+
}
|
|
70
|
+
function resetNetwork() {
|
|
71
|
+
config = null;
|
|
72
|
+
debugMode = false;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/core/network.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in mobile network capture → api_call events (parity with the web SDK).
|
|
3
|
+
*
|
|
4
|
+
* Patches global fetch + XMLHttpRequest and, for each request, emits a SANITIZED
|
|
5
|
+
* api_call: method, host, path (query string + hash stripped), status, durationMs.
|
|
6
|
+
* NEVER captures request/response bodies or headers, and skips the SDK's own backend
|
|
7
|
+
* calls (to apiBase / /api/engagement/) so telemetry doesn't observe itself.
|
|
8
|
+
*/
|
|
9
|
+
type ApiCall = {
|
|
10
|
+
method: string;
|
|
11
|
+
host: string;
|
|
12
|
+
path: string;
|
|
13
|
+
url: string;
|
|
14
|
+
status: number;
|
|
15
|
+
durationMs: number;
|
|
16
|
+
success: boolean;
|
|
17
|
+
};
|
|
18
|
+
type EmitFn = (call: ApiCall) => void;
|
|
19
|
+
export declare function startNetworkCapture(base: string, emitFn: EmitFn): void;
|
|
20
|
+
export declare function stopNetworkCapture(): void;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=networkCapture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"networkCapture.d.ts","sourceRoot":"","sources":["../../src/core/networkCapture.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,KAAK,OAAO,GAAG;IACb,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IACxD,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;CACtD,CAAC;AACF,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;AAiCtC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAuCtE;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAMzC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startNetworkCapture = startNetworkCapture;
|
|
4
|
+
exports.stopNetworkCapture = stopNetworkCapture;
|
|
5
|
+
let emit = null;
|
|
6
|
+
let apiBase = '';
|
|
7
|
+
let origFetch = null;
|
|
8
|
+
let origXhrOpen = null;
|
|
9
|
+
let origXhrSend = null;
|
|
10
|
+
/** Strip query/hash, split host+path, and drop the SDK's own backend calls. */
|
|
11
|
+
function sanitize(rawUrl) {
|
|
12
|
+
try {
|
|
13
|
+
if (!rawUrl)
|
|
14
|
+
return null;
|
|
15
|
+
if (apiBase && rawUrl.indexOf(apiBase) === 0)
|
|
16
|
+
return null; // our own ingestion calls
|
|
17
|
+
if (rawUrl.indexOf('/api/engagement/') !== -1)
|
|
18
|
+
return null;
|
|
19
|
+
const noQuery = rawUrl.split('?')[0].split('#')[0];
|
|
20
|
+
const m = noQuery.match(/^https?:\/\/([^/]+)(\/.*)?$/i);
|
|
21
|
+
if (m)
|
|
22
|
+
return { host: m[1], path: m[2] || '/', url: noQuery };
|
|
23
|
+
return { host: '', path: noQuery, url: noQuery }; // relative URL
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function report(method, rawUrl, status, durationMs) {
|
|
30
|
+
if (!emit)
|
|
31
|
+
return;
|
|
32
|
+
const s = sanitize(String(rawUrl));
|
|
33
|
+
if (!s)
|
|
34
|
+
return;
|
|
35
|
+
try {
|
|
36
|
+
emit({
|
|
37
|
+
method: (method || 'GET').toUpperCase(), host: s.host, path: s.path, url: s.url,
|
|
38
|
+
status: status || 0, durationMs: Math.round(durationMs), success: status >= 200 && status < 300,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch { /* best-effort */ }
|
|
42
|
+
}
|
|
43
|
+
function startNetworkCapture(base, emitFn) {
|
|
44
|
+
if (emit)
|
|
45
|
+
return; // already patched
|
|
46
|
+
apiBase = base || '';
|
|
47
|
+
emit = emitFn;
|
|
48
|
+
// ── fetch ──
|
|
49
|
+
const g = globalThis;
|
|
50
|
+
if (typeof g.fetch === 'function') {
|
|
51
|
+
origFetch = g.fetch;
|
|
52
|
+
g.fetch = function (input, init) {
|
|
53
|
+
const method = (init?.method || (typeof input === 'object' && 'method' in input ? input.method : '') || 'GET');
|
|
54
|
+
const url = typeof input === 'string' ? input : input.toString?.() || input.url || '';
|
|
55
|
+
const start = Date.now();
|
|
56
|
+
return origFetch.call(this, input, init)
|
|
57
|
+
.then((res) => { report(method, url, res.status, Date.now() - start); return res; })
|
|
58
|
+
.catch((err) => { report(method, url, 0, Date.now() - start); throw err; });
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// ── XMLHttpRequest ──
|
|
62
|
+
const XHR = g.XMLHttpRequest;
|
|
63
|
+
if (XHR && XHR.prototype) {
|
|
64
|
+
origXhrOpen = XHR.prototype.open;
|
|
65
|
+
origXhrSend = XHR.prototype.send;
|
|
66
|
+
XHR.prototype.open = function (method, url, ...rest) {
|
|
67
|
+
this.__cxp = { method, url, start: 0 };
|
|
68
|
+
return origXhrOpen.call(this, method, url, ...rest);
|
|
69
|
+
};
|
|
70
|
+
XHR.prototype.send = function (...args) {
|
|
71
|
+
const c = this.__cxp;
|
|
72
|
+
if (c) {
|
|
73
|
+
c.start = Date.now();
|
|
74
|
+
this.addEventListener('loadend', () => {
|
|
75
|
+
try {
|
|
76
|
+
report(c.method, c.url, this.status, Date.now() - c.start);
|
|
77
|
+
}
|
|
78
|
+
catch { /* noop */ }
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return origXhrSend.call(this, ...args);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function stopNetworkCapture() {
|
|
86
|
+
const g = globalThis;
|
|
87
|
+
if (origFetch) {
|
|
88
|
+
g.fetch = origFetch;
|
|
89
|
+
origFetch = null;
|
|
90
|
+
}
|
|
91
|
+
const XHR = g.XMLHttpRequest;
|
|
92
|
+
if (XHR && origXhrOpen) {
|
|
93
|
+
XHR.prototype.open = origXhrOpen;
|
|
94
|
+
XHR.prototype.send = origXhrSend;
|
|
95
|
+
origXhrOpen = null;
|
|
96
|
+
origXhrSend = null;
|
|
97
|
+
}
|
|
98
|
+
emit = null;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=networkCapture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"networkCapture.js","sourceRoot":"","sources":["../../src/core/networkCapture.ts"],"names":[],"mappings":"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"}
|