noibu-react-native 0.2.12 → 0.2.13
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/CHANGELOG.md +21 -0
- package/README.md +69 -0
- package/dist/api/ClientConfig.d.ts +3 -0
- package/dist/api/ClientConfig.js +3 -0
- package/dist/api/MetroplexSocket.d.ts +1 -1
- package/dist/api/MetroplexSocket.js +11 -5
- package/dist/constants.js +1 -1
- package/dist/mobileTransformer/mobile-replay/index.d.ts +10 -0
- package/dist/mobileTransformer/mobile-replay/index.js +57 -0
- package/dist/mobileTransformer/mobile-replay/mobile.types.d.ts +312 -0
- package/dist/mobileTransformer/mobile-replay/mobile.types.js +11 -0
- package/dist/mobileTransformer/mobile-replay/rrweb.d.ts +573 -0
- package/dist/mobileTransformer/mobile-replay/rrweb.js +39 -0
- package/dist/mobileTransformer/mobile-replay/schema/mobile/rr-mobile-schema.json.js +1559 -0
- package/dist/mobileTransformer/mobile-replay/schema/web/rr-web-schema.json.js +1183 -0
- package/dist/mobileTransformer/mobile-replay/transformer/colors.d.ts +1 -0
- package/dist/mobileTransformer/mobile-replay/transformer/colors.js +43 -0
- package/dist/mobileTransformer/mobile-replay/transformer/screen-chrome.d.ts +13 -0
- package/dist/mobileTransformer/mobile-replay/transformer/screen-chrome.js +142 -0
- package/dist/mobileTransformer/mobile-replay/transformer/transformers.d.ts +59 -0
- package/dist/mobileTransformer/mobile-replay/transformer/transformers.js +1160 -0
- package/dist/mobileTransformer/mobile-replay/transformer/types.d.ts +40 -0
- package/dist/mobileTransformer/mobile-replay/transformer/wireframeStyle.d.ts +16 -0
- package/dist/mobileTransformer/mobile-replay/transformer/wireframeStyle.js +197 -0
- package/dist/mobileTransformer/utils.d.ts +1 -0
- package/dist/mobileTransformer/utils.js +5 -0
- package/dist/monitors/http-tools/GqlErrorValidator.js +4 -3
- package/dist/sessionRecorder/SessionRecorder.js +7 -4
- package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +23 -3
- package/dist/sessionRecorder/types.d.ts +1 -1
- package/dist/utils/piiRedactor.js +15 -2
- package/dist/utils/piiRedactor.test.d.ts +1 -0
- package/ios/IOSPocEmitter.h +7 -0
- package/ios/IOSPocEmitter.m +33 -0
- package/noibu-react-native.podspec +50 -0
- package/package.json +17 -4
- package/android/.gitignore +0 -13
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface StyleOverride {
|
|
2
|
+
borderWidth?: string | number;
|
|
3
|
+
borderRadius?: string | number;
|
|
4
|
+
borderColor?: string;
|
|
5
|
+
bottom?: boolean;
|
|
6
|
+
'z-index'?: number;
|
|
7
|
+
paddingLeft?: string | number;
|
|
8
|
+
paddingRight?: string | number;
|
|
9
|
+
paddingTop?: string | number;
|
|
10
|
+
paddingBottom?: string | number;
|
|
11
|
+
verticalAlign?: 'top' | 'center' | 'bottom';
|
|
12
|
+
horizontalAlign?: 'left' | 'center' | 'right';
|
|
13
|
+
fontSize?: string | number;
|
|
14
|
+
fontFamily?: string;
|
|
15
|
+
color?: string;
|
|
16
|
+
backgroundColor?: string;
|
|
17
|
+
backgroundImage?: string;
|
|
18
|
+
backgroundSize?: string;
|
|
19
|
+
backgroundRepeat?: string;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Represents the context in which a data conversion is happening.
|
|
24
|
+
* Includes information for id sequencing and timestamps to ensure
|
|
25
|
+
* consistent data handling during transformations.
|
|
26
|
+
*/
|
|
27
|
+
export interface ConversionContext {
|
|
28
|
+
idSequence: Generator<number>;
|
|
29
|
+
timestamp?: number;
|
|
30
|
+
debugMode?: boolean;
|
|
31
|
+
styleOverride?: StyleOverride;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Represents the result of a conversion process.
|
|
35
|
+
* Contains the transformed data and relevant information for success or failure handling.
|
|
36
|
+
*/
|
|
37
|
+
export interface ConversionResult<T = unknown> {
|
|
38
|
+
result: T;
|
|
39
|
+
context: ConversionContext;
|
|
40
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { wireframe, wireframeProgress } from '../mobile.types';
|
|
2
|
+
import { StyleOverride } from './types';
|
|
3
|
+
export declare function asStyleString(styleParts: string[]): string;
|
|
4
|
+
export declare function makeDimensionStyles(wireframe: wireframe): string;
|
|
5
|
+
export declare function makePositionStyles(wireframe: wireframe, styleOverride?: StyleOverride): string;
|
|
6
|
+
export declare function makeIndeterminateProgressStyles(wireframe: wireframeProgress, styleOverride?: StyleOverride): string;
|
|
7
|
+
export declare function makeDeterminateProgressStyles(wireframe: wireframeProgress, styleOverride?: StyleOverride): string;
|
|
8
|
+
/**
|
|
9
|
+
* normally use makeStylesString instead, but sometimes you need styles without any colors applied
|
|
10
|
+
* */
|
|
11
|
+
export declare function makeMinimalStyles(wireframe: wireframe, styleOverride?: StyleOverride): string;
|
|
12
|
+
export declare function makeBackgroundStyles(wireframe: wireframe, styleOverride?: StyleOverride): string;
|
|
13
|
+
export declare function makeColorStyles(wireframe: wireframe, styleOverride?: StyleOverride): string;
|
|
14
|
+
export declare function makeStylesString(wireframe: wireframe, styleOverride?: StyleOverride): string;
|
|
15
|
+
export declare function makeHTMLStyles(): string;
|
|
16
|
+
export declare function makeBodyStyles(): string;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { dataURIOrPNG } from './transformers.js';
|
|
2
|
+
|
|
3
|
+
function ensureTrailingSemicolon(styles) {
|
|
4
|
+
return styles.endsWith(';') ? styles : styles + ';';
|
|
5
|
+
}
|
|
6
|
+
function stripTrailingSemicolon(styles) {
|
|
7
|
+
return styles.endsWith(';') ? styles.slice(0, -1) : styles;
|
|
8
|
+
}
|
|
9
|
+
function asStyleString(styleParts) {
|
|
10
|
+
if (styleParts.length === 0) {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
return ensureTrailingSemicolon(styleParts
|
|
14
|
+
.map(stripTrailingSemicolon)
|
|
15
|
+
.filter(x => !!x)
|
|
16
|
+
.join(';'));
|
|
17
|
+
}
|
|
18
|
+
function isNumber(candidate) {
|
|
19
|
+
return typeof candidate === 'number' && Number.isFinite(candidate);
|
|
20
|
+
}
|
|
21
|
+
function isString(candidate) {
|
|
22
|
+
return typeof candidate === 'string' || candidate instanceof String;
|
|
23
|
+
}
|
|
24
|
+
function isUnitLike(candidate) {
|
|
25
|
+
return isNumber(candidate) || (isString(candidate) && candidate.length > 0);
|
|
26
|
+
}
|
|
27
|
+
function ensureUnit(value) {
|
|
28
|
+
return isNumber(value) ? `${value}px` : value.replace(/px$/g, '') + 'px';
|
|
29
|
+
}
|
|
30
|
+
function makeBorderStyles(wireframe, styleOverride) {
|
|
31
|
+
const styleParts = [];
|
|
32
|
+
const combinedStyles = Object.assign(Object.assign({}, wireframe.style), styleOverride);
|
|
33
|
+
if (isUnitLike(combinedStyles.borderWidth)) {
|
|
34
|
+
const borderWidth = ensureUnit(combinedStyles.borderWidth);
|
|
35
|
+
styleParts.push(`border-width: ${borderWidth}`);
|
|
36
|
+
}
|
|
37
|
+
if (isUnitLike(combinedStyles.borderRadius)) {
|
|
38
|
+
const borderRadius = ensureUnit(combinedStyles.borderRadius);
|
|
39
|
+
styleParts.push(`border-radius: ${borderRadius}`);
|
|
40
|
+
}
|
|
41
|
+
if (combinedStyles === null || combinedStyles === void 0 ? void 0 : combinedStyles.borderColor) {
|
|
42
|
+
styleParts.push(`border-color: ${combinedStyles.borderColor}`);
|
|
43
|
+
}
|
|
44
|
+
if (styleParts.length > 0) {
|
|
45
|
+
styleParts.push(`border-style: solid`);
|
|
46
|
+
}
|
|
47
|
+
return asStyleString(styleParts);
|
|
48
|
+
}
|
|
49
|
+
function makeDimensionStyles(wireframe) {
|
|
50
|
+
const styleParts = [];
|
|
51
|
+
if (wireframe.width === '100vw') {
|
|
52
|
+
styleParts.push(`width: 100vw`);
|
|
53
|
+
}
|
|
54
|
+
else if (isNumber(wireframe.width)) {
|
|
55
|
+
styleParts.push(`width: ${ensureUnit(wireframe.width)}`);
|
|
56
|
+
}
|
|
57
|
+
if (isNumber(wireframe.height)) {
|
|
58
|
+
styleParts.push(`height: ${ensureUnit(wireframe.height)}`);
|
|
59
|
+
}
|
|
60
|
+
return asStyleString(styleParts);
|
|
61
|
+
}
|
|
62
|
+
function makePositionStyles(wireframe, styleOverride) {
|
|
63
|
+
const styleParts = [];
|
|
64
|
+
styleParts.push(makeDimensionStyles(wireframe));
|
|
65
|
+
if (styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.bottom) {
|
|
66
|
+
styleParts.push(`bottom: 0`);
|
|
67
|
+
styleParts.push(`position: fixed`);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const posX = wireframe.x || 0;
|
|
71
|
+
const posY = wireframe.y || 0;
|
|
72
|
+
if (isNumber(posX) || isNumber(posY)) {
|
|
73
|
+
styleParts.push(`position: fixed`);
|
|
74
|
+
if (isNumber(posX)) {
|
|
75
|
+
styleParts.push(`left: ${ensureUnit(posX)}`);
|
|
76
|
+
}
|
|
77
|
+
if (isNumber(posY)) {
|
|
78
|
+
styleParts.push(`top: ${ensureUnit(posY)}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride['z-index']) {
|
|
83
|
+
styleParts.push(`z-index: ${styleOverride['z-index']}`);
|
|
84
|
+
}
|
|
85
|
+
return asStyleString(styleParts);
|
|
86
|
+
}
|
|
87
|
+
function makeLayoutStyles(wireframe, styleOverride) {
|
|
88
|
+
const styleParts = [];
|
|
89
|
+
const combinedStyles = Object.assign(Object.assign({}, wireframe.style), styleOverride);
|
|
90
|
+
if (combinedStyles.verticalAlign) {
|
|
91
|
+
styleParts.push(`align-items: ${{ top: 'flex-start', center: 'center', bottom: 'flex-end' }[combinedStyles.verticalAlign]}`);
|
|
92
|
+
}
|
|
93
|
+
if (combinedStyles.horizontalAlign) {
|
|
94
|
+
styleParts.push(`justify-content: ${{ left: 'flex-start', center: 'center', right: 'flex-end' }[combinedStyles.horizontalAlign]}`);
|
|
95
|
+
}
|
|
96
|
+
if (styleParts.length) {
|
|
97
|
+
styleParts.push(`display: flex`);
|
|
98
|
+
}
|
|
99
|
+
if (isUnitLike(combinedStyles.paddingLeft)) {
|
|
100
|
+
styleParts.push(`padding-left: ${ensureUnit(combinedStyles.paddingLeft)}`);
|
|
101
|
+
}
|
|
102
|
+
if (isUnitLike(combinedStyles.paddingRight)) {
|
|
103
|
+
styleParts.push(`padding-right: ${ensureUnit(combinedStyles.paddingRight)}`);
|
|
104
|
+
}
|
|
105
|
+
if (isUnitLike(combinedStyles.paddingTop)) {
|
|
106
|
+
styleParts.push(`padding-top: ${ensureUnit(combinedStyles.paddingTop)}`);
|
|
107
|
+
}
|
|
108
|
+
if (isUnitLike(combinedStyles.paddingBottom)) {
|
|
109
|
+
styleParts.push(`padding-bottom: ${ensureUnit(combinedStyles.paddingBottom)}`);
|
|
110
|
+
}
|
|
111
|
+
return asStyleString(styleParts);
|
|
112
|
+
}
|
|
113
|
+
function makeFontStyles(wireframe, styleOverride) {
|
|
114
|
+
const styleParts = [];
|
|
115
|
+
const combinedStyles = Object.assign(Object.assign({}, wireframe.style), styleOverride);
|
|
116
|
+
if (isUnitLike(combinedStyles.fontSize)) {
|
|
117
|
+
styleParts.push(`font-size: ${ensureUnit(combinedStyles === null || combinedStyles === void 0 ? void 0 : combinedStyles.fontSize)}`);
|
|
118
|
+
}
|
|
119
|
+
if (combinedStyles.fontFamily) {
|
|
120
|
+
styleParts.push(`font-family: ${combinedStyles.fontFamily}`);
|
|
121
|
+
}
|
|
122
|
+
return asStyleString(styleParts);
|
|
123
|
+
}
|
|
124
|
+
function makeIndeterminateProgressStyles(wireframe, styleOverride) {
|
|
125
|
+
const combinedStyles = Object.assign(Object.assign({}, wireframe.style), styleOverride);
|
|
126
|
+
return asStyleString([
|
|
127
|
+
makeBackgroundStyles(wireframe, styleOverride),
|
|
128
|
+
makePositionStyles(wireframe),
|
|
129
|
+
`border: 4px solid ${combinedStyles.borderColor || combinedStyles.color || 'transparent'};`,
|
|
130
|
+
`border-radius: 50%;border-top: 4px solid #fff;`,
|
|
131
|
+
`animation: spin 2s linear infinite;`,
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
134
|
+
function makeDeterminateProgressStyles(wireframe, styleOverride) {
|
|
135
|
+
const combinedStyles = Object.assign(Object.assign({}, wireframe.style), styleOverride);
|
|
136
|
+
const radialGradient = `radial-gradient(closest-side, white 80%, transparent 0 99.9%, white 0)`;
|
|
137
|
+
const conicGradient = `conic-gradient(${combinedStyles.color || 'black'} calc(${wireframe.value} * 1%), ${combinedStyles.backgroundColor} 0)`;
|
|
138
|
+
return asStyleString([
|
|
139
|
+
makeBackgroundStyles(wireframe, styleOverride),
|
|
140
|
+
makePositionStyles(wireframe),
|
|
141
|
+
'border-radius: 50%',
|
|
142
|
+
`background: ${radialGradient}, ${conicGradient}`,
|
|
143
|
+
]);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* normally use makeStylesString instead, but sometimes you need styles without any colors applied
|
|
147
|
+
* */
|
|
148
|
+
function makeMinimalStyles(wireframe, styleOverride) {
|
|
149
|
+
return asStyleString([
|
|
150
|
+
makePositionStyles(wireframe, styleOverride),
|
|
151
|
+
makeLayoutStyles(wireframe, styleOverride),
|
|
152
|
+
makeFontStyles(wireframe, styleOverride),
|
|
153
|
+
]);
|
|
154
|
+
}
|
|
155
|
+
function makeBackgroundStyles(wireframe, styleOverride) {
|
|
156
|
+
let styleParts = [];
|
|
157
|
+
const combinedStyles = Object.assign(Object.assign({}, wireframe.style), styleOverride);
|
|
158
|
+
if (combinedStyles.backgroundColor) {
|
|
159
|
+
styleParts.push(`background-color: ${combinedStyles.backgroundColor}`);
|
|
160
|
+
}
|
|
161
|
+
if (combinedStyles.backgroundImage) {
|
|
162
|
+
const backgroundImageURL = combinedStyles.backgroundImage.startsWith('url(')
|
|
163
|
+
? combinedStyles.backgroundImage
|
|
164
|
+
: `url('${dataURIOrPNG(combinedStyles.backgroundImage)}')`;
|
|
165
|
+
styleParts = styleParts.concat([
|
|
166
|
+
`background-image: ${backgroundImageURL}`,
|
|
167
|
+
`background-size: ${combinedStyles.backgroundSize || 'contain'}`,
|
|
168
|
+
`background-repeat: ${combinedStyles.backgroundRepeat || 'no-repeat'}`,
|
|
169
|
+
]);
|
|
170
|
+
}
|
|
171
|
+
return asStyleString(styleParts);
|
|
172
|
+
}
|
|
173
|
+
function makeColorStyles(wireframe, styleOverride) {
|
|
174
|
+
const combinedStyles = Object.assign(Object.assign({}, wireframe.style), styleOverride);
|
|
175
|
+
const styleParts = [
|
|
176
|
+
makeBackgroundStyles(wireframe, styleOverride),
|
|
177
|
+
makeBorderStyles(wireframe, styleOverride),
|
|
178
|
+
];
|
|
179
|
+
if (combinedStyles.color) {
|
|
180
|
+
styleParts.push(`color: ${combinedStyles.color}`);
|
|
181
|
+
}
|
|
182
|
+
return asStyleString(styleParts);
|
|
183
|
+
}
|
|
184
|
+
function makeStylesString(wireframe, styleOverride) {
|
|
185
|
+
return asStyleString([
|
|
186
|
+
makeColorStyles(wireframe, styleOverride),
|
|
187
|
+
makeMinimalStyles(wireframe, styleOverride),
|
|
188
|
+
]);
|
|
189
|
+
}
|
|
190
|
+
function makeHTMLStyles() {
|
|
191
|
+
return 'height: 100vh; width: 100vw;';
|
|
192
|
+
}
|
|
193
|
+
function makeBodyStyles() {
|
|
194
|
+
return 'height: 100vh; width: 100vw;';
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export { asStyleString, makeBackgroundStyles, makeBodyStyles, makeColorStyles, makeDeterminateProgressStyles, makeDimensionStyles, makeHTMLStyles, makeIndeterminateProgressStyles, makeMinimalStyles, makePositionStyles, makeStylesString };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isObject(candidate: unknown): candidate is Record<string, unknown>;
|
|
@@ -43,13 +43,14 @@ class GqlErrorValidator {
|
|
|
43
43
|
static fromXhr(url, xhr) {
|
|
44
44
|
return __awaiter(this, void 0, void 0, function* () {
|
|
45
45
|
try {
|
|
46
|
-
const isResponseValid =
|
|
46
|
+
const isResponseValid = xhr instanceof XMLHttpRequest && xhr.status >= 200 && xhr.status <= 299;
|
|
47
47
|
if (!isResponseValid) {
|
|
48
48
|
return null;
|
|
49
49
|
}
|
|
50
50
|
let contentType;
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const xhrWithHeaders = xhr;
|
|
52
|
+
if (xhrWithHeaders.noibuRequestHeaders) {
|
|
53
|
+
contentType = xhrWithHeaders.noibuRequestHeaders.get(CONTENT_TYPE);
|
|
53
54
|
}
|
|
54
55
|
if (this._shouldHandleRequest(url, contentType)) {
|
|
55
56
|
let data = null;
|
|
@@ -39,9 +39,7 @@ class SessionRecorder extends Singleton {
|
|
|
39
39
|
const nativeSessionRecorderConfig = {
|
|
40
40
|
logLevel: LogLevel.Verbose,
|
|
41
41
|
};
|
|
42
|
-
|
|
43
|
-
initialize('abc1234', nativeSessionRecorderConfig);
|
|
44
|
-
}
|
|
42
|
+
initialize('abc1234', nativeSessionRecorderConfig);
|
|
45
43
|
addSafeEventListener(window, 'click', () => this.handleFragPost());
|
|
46
44
|
}
|
|
47
45
|
/** Sets up the page hide handler to try to push remaining video events */
|
|
@@ -167,7 +165,12 @@ class SessionRecorder extends Singleton {
|
|
|
167
165
|
pack(recorderEvent) {
|
|
168
166
|
return __awaiter(this, void 0, void 0, function* () {
|
|
169
167
|
// return JSON.stringify(recorderEvent);
|
|
170
|
-
|
|
168
|
+
if (Platform.OS === 'ios') {
|
|
169
|
+
return recorderEvent;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
return SessionRecorder.compress(recorderEvent);
|
|
173
|
+
}
|
|
171
174
|
});
|
|
172
175
|
}
|
|
173
176
|
/** Compresses the snapshot */
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Platform, NativeEventEmitter, NativeModules } from 'react-native';
|
|
2
2
|
import { noibuLog } from '../utils/log.js';
|
|
3
|
+
import { transformEventToWeb } from '../mobileTransformer/mobile-replay/index.js';
|
|
3
4
|
|
|
4
5
|
const LINKING_ERROR = `The package 'noibu-session-replay' doesn't seem to be linked. Make sure: \n\n` +
|
|
5
6
|
// Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) + TODO: add back when iOS is supported.
|
|
6
7
|
'- You rebuilt the app after installing the package\n' +
|
|
7
8
|
'- You are not using Expo Go\n';
|
|
8
|
-
const { NativeSessionRecorder } = NativeModules;
|
|
9
|
+
const { NativeSessionRecorder, IOSPocEmitter } = NativeModules;
|
|
9
10
|
let nativeModuleEmitter;
|
|
10
|
-
const SupportedPlatforms = ['android'];
|
|
11
|
+
const SupportedPlatforms = ['android', 'ios'];
|
|
11
12
|
/** The level of logging to show in the device logcat stream. */
|
|
12
13
|
// eslint-disable-next-line no-shadow
|
|
13
14
|
var LogLevel;
|
|
@@ -25,6 +26,11 @@ var LogLevel;
|
|
|
25
26
|
* param config [OPTIONAL] The sessionreplay config, if not provided default values are used.
|
|
26
27
|
*/
|
|
27
28
|
function initialize(projectId, config) {
|
|
29
|
+
if (Platform.OS === 'ios') {
|
|
30
|
+
nativeModuleEmitter = new NativeEventEmitter(IOSPocEmitter);
|
|
31
|
+
IOSPocEmitter.initialize();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
28
34
|
if (!(typeof config === 'object' || typeof config === 'undefined')) {
|
|
29
35
|
throw Error('Invalid session recording initialization arguments. Please check the docs for assitance.');
|
|
30
36
|
}
|
|
@@ -68,6 +74,20 @@ function subscribeToNativeEvent(callback) {
|
|
|
68
74
|
nativeModuleEmitter.addListener('noibuRecordingEvent', callback);
|
|
69
75
|
// return () => subscription.remove();
|
|
70
76
|
}
|
|
77
|
+
if (Platform.OS === 'ios') {
|
|
78
|
+
nativeModuleEmitter.addListener('iosPOCRecordingEvent', event => {
|
|
79
|
+
try {
|
|
80
|
+
let parsedMessage = JSON.parse(event.message);
|
|
81
|
+
if (Array.isArray(parsedMessage)) {
|
|
82
|
+
parsedMessage = parsedMessage[0];
|
|
83
|
+
}
|
|
84
|
+
const transformedEvent = transformEventToWeb(parsedMessage);
|
|
85
|
+
callback({ message: transformedEvent });
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
71
91
|
return () => { };
|
|
72
92
|
}
|
|
73
93
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { iterateObjectRecursively } from './object.js';
|
|
2
2
|
import { PII_REDACTION_REPLACEMENT_STRING, PII_EMAIL_PATTERN } from '../constants.js';
|
|
3
3
|
import { stringifyJSON } from './function.js';
|
|
4
|
+
import ClientConfig from '../api/ClientConfig.js';
|
|
4
5
|
|
|
5
6
|
// Regex patterns for a best-effort attempt at blocking PII in HTTP requests
|
|
6
7
|
const HTTP_PII_BLOCKING_PATTERNS = [
|
|
@@ -64,7 +65,7 @@ const exactFieldsToRedact = [
|
|
|
64
65
|
*/
|
|
65
66
|
function shouldRedact(field) {
|
|
66
67
|
// check for exact and fuzzy matches
|
|
67
|
-
return
|
|
68
|
+
return getExactFieldsToRedact().some(v => field === v) || getFuzzyFieldsToRedact().some(v => field.indexOf(v) >= 0);
|
|
68
69
|
}
|
|
69
70
|
/**
|
|
70
71
|
* Try to parse content as a JSON object and
|
|
@@ -116,11 +117,23 @@ function removePII(content) {
|
|
|
116
117
|
}
|
|
117
118
|
content = tryParseObjectAndRemovePII(content);
|
|
118
119
|
// Go through each of the PII matching patterns
|
|
119
|
-
|
|
120
|
+
getHttpPiiBlockingPatterns().forEach(pattern => {
|
|
120
121
|
// Replace all matches with the appropriate number of asterisks
|
|
121
122
|
content = content.replace(pattern, PII_REDACTION_REPLACEMENT_STRING);
|
|
122
123
|
});
|
|
123
124
|
return content;
|
|
124
125
|
}
|
|
126
|
+
function getHttpPiiBlockingPatterns() {
|
|
127
|
+
var _a;
|
|
128
|
+
return (_a = ClientConfig.getInstance().httpPiiBlockingPatterns) !== null && _a !== void 0 ? _a : HTTP_PII_BLOCKING_PATTERNS;
|
|
129
|
+
}
|
|
130
|
+
function getFuzzyFieldsToRedact() {
|
|
131
|
+
var _a;
|
|
132
|
+
return (_a = ClientConfig.getInstance().fuzzyFieldsToRedact) !== null && _a !== void 0 ? _a : fuzzyFieldsToRedact;
|
|
133
|
+
}
|
|
134
|
+
function getExactFieldsToRedact() {
|
|
135
|
+
var _a;
|
|
136
|
+
return (_a = ClientConfig.getInstance().exactFieldsToRedact) !== null && _a !== void 0 ? _a : exactFieldsToRedact;
|
|
137
|
+
}
|
|
125
138
|
|
|
126
139
|
export { removePII, shouldRedact };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#import "IOSPocEmitter.h"
|
|
2
|
+
@import NoibuSDK;
|
|
3
|
+
@implementation IOSPocEmitter
|
|
4
|
+
|
|
5
|
+
// Module registration
|
|
6
|
+
RCT_EXPORT_MODULE();
|
|
7
|
+
|
|
8
|
+
// Supported events for React Native
|
|
9
|
+
- (NSArray<NSString *> *)supportedEvents {
|
|
10
|
+
return @[@"iosPOCRecordingEvent"];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
RCT_EXPORT_METHOD(initialize) {
|
|
14
|
+
NSString *NOIBU_API_KEY = @"NOIBU_API_KEY";
|
|
15
|
+
NSString *NOIBU_HOST = @"https://noibu.com/";
|
|
16
|
+
// Create and configure the NoibuConfig object
|
|
17
|
+
NoibuConfig *config = [[NoibuConfig alloc] apiKey:NOIBU_API_KEY host:NOIBU_HOST];
|
|
18
|
+
// config.debug = YES; // Enable debug logging to see transformed events
|
|
19
|
+
// Define the callback for transformed events
|
|
20
|
+
config.onMobileEventTransformed = ^(NSString *transformedData) {
|
|
21
|
+
if ([self bridge]) { // Ensure the bridge is initialized
|
|
22
|
+
[self sendEventWithName:@"iosPOCRecordingEvent" body:@{@"message": transformedData}];
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
[[NoibuSDKManager shared] setup:config];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// React Native requires this to indicate if the module needs to be initialized on the main thread
|
|
29
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
30
|
+
return YES;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
5
|
+
|
|
6
|
+
Pod::Spec.new do |s|
|
|
7
|
+
s.name = "noibu-react-native"
|
|
8
|
+
s.version = package["version"]
|
|
9
|
+
s.summary = package["description"]
|
|
10
|
+
s.homepage = "https://www.npmjs.com/package/noibu-react-native"
|
|
11
|
+
s.license = package["license"]
|
|
12
|
+
s.authors = package["author"]
|
|
13
|
+
|
|
14
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
15
|
+
#s.source = { :git => "https://www.github.com/aleguia.git", :tag => "#{s.version}" }
|
|
16
|
+
s.source = { :path => "." }
|
|
17
|
+
|
|
18
|
+
# Include source files
|
|
19
|
+
|
|
20
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
21
|
+
s.public_header_files = "ios/**/*.{h}" # Expose public headers
|
|
22
|
+
|
|
23
|
+
#s.vendored_frameworks = "ios/SessionRecorder.xcframework"
|
|
24
|
+
#s.vendored_frameworks = "ios/Noibu.xcframework"
|
|
25
|
+
|
|
26
|
+
s.dependency 'NoibuSDK'
|
|
27
|
+
s.pod_target_xcconfig = {
|
|
28
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/noibu-react-native/ios/**\""
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
32
|
+
install_modules_dependencies(s)
|
|
33
|
+
else
|
|
34
|
+
s.dependency "React-Core"
|
|
35
|
+
|
|
36
|
+
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
37
|
+
s.compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1'
|
|
38
|
+
s.pod_target_xcconfig = {
|
|
39
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
40
|
+
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
41
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
42
|
+
}
|
|
43
|
+
s.dependency "React-Codegen"
|
|
44
|
+
s.dependency "RCT-Folly"
|
|
45
|
+
s.dependency "RCTRequired"
|
|
46
|
+
s.dependency "RCTTypeSafety"
|
|
47
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
package/package.json
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "noibu-react-native",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.13",
|
|
4
4
|
"targetNjsVersion": "1.0.104",
|
|
5
5
|
"description": "React-Native SDK for NoibuJS to collect errors in React-Native applications",
|
|
6
6
|
"main": "dist/entry/index.js",
|
|
7
7
|
"types": "dist/entry/index.d.ts",
|
|
8
8
|
"files": [
|
|
9
|
-
"android
|
|
9
|
+
"android",
|
|
10
10
|
"dist/*",
|
|
11
|
-
"README.md"
|
|
11
|
+
"README.md",
|
|
12
|
+
"CHANGELOG.md",
|
|
13
|
+
"ios",
|
|
14
|
+
"cpp",
|
|
15
|
+
"*.podspec",
|
|
16
|
+
"!ios/build",
|
|
17
|
+
"!android/build",
|
|
18
|
+
"!android/gradle",
|
|
19
|
+
"!android/gradlew",
|
|
20
|
+
"!android/gradlew.bat",
|
|
21
|
+
"!android/local.properties"
|
|
12
22
|
],
|
|
13
23
|
"author": "Noibu Inc",
|
|
14
24
|
"license": "ISC",
|
|
@@ -61,7 +71,7 @@
|
|
|
61
71
|
"@tsconfig/react-native": "^3.0.2",
|
|
62
72
|
"@types/jest": "^29.5.14",
|
|
63
73
|
"@types/node": "^20.2.3",
|
|
64
|
-
"@types/react": "
|
|
74
|
+
"@types/react": "18.2.6",
|
|
65
75
|
"@types/react-test-renderer": "^18.0.0",
|
|
66
76
|
"@typescript-eslint/eslint-plugin": "^8.19.1",
|
|
67
77
|
"@typescript-eslint/parser": "^8.19.1",
|
|
@@ -86,5 +96,8 @@
|
|
|
86
96
|
"rollup-plugin-dotenv": "^0.5.0",
|
|
87
97
|
"ts-jest": "^29.2.5",
|
|
88
98
|
"typescript": "^5.5.3"
|
|
99
|
+
},
|
|
100
|
+
"resolutions": {
|
|
101
|
+
"@types/react": "18.0.30"
|
|
89
102
|
}
|
|
90
103
|
}
|