noibu-react-native 0.2.12 → 0.2.14

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +69 -0
  3. package/dist/api/ClientConfig.d.ts +3 -0
  4. package/dist/api/ClientConfig.js +3 -0
  5. package/dist/api/MetroplexSocket.d.ts +1 -1
  6. package/dist/api/MetroplexSocket.js +11 -5
  7. package/dist/constants.js +1 -1
  8. package/dist/mobileTransformer/mobile-replay/index.d.ts +10 -0
  9. package/dist/mobileTransformer/mobile-replay/index.js +57 -0
  10. package/dist/mobileTransformer/mobile-replay/mobile.types.d.ts +312 -0
  11. package/dist/mobileTransformer/mobile-replay/mobile.types.js +11 -0
  12. package/dist/mobileTransformer/mobile-replay/rrweb.d.ts +573 -0
  13. package/dist/mobileTransformer/mobile-replay/rrweb.js +39 -0
  14. package/dist/mobileTransformer/mobile-replay/schema/mobile/rr-mobile-schema.json.js +1559 -0
  15. package/dist/mobileTransformer/mobile-replay/schema/web/rr-web-schema.json.js +1183 -0
  16. package/dist/mobileTransformer/mobile-replay/transformer/colors.d.ts +1 -0
  17. package/dist/mobileTransformer/mobile-replay/transformer/colors.js +43 -0
  18. package/dist/mobileTransformer/mobile-replay/transformer/screen-chrome.d.ts +13 -0
  19. package/dist/mobileTransformer/mobile-replay/transformer/screen-chrome.js +142 -0
  20. package/dist/mobileTransformer/mobile-replay/transformer/transformers.d.ts +59 -0
  21. package/dist/mobileTransformer/mobile-replay/transformer/transformers.js +1160 -0
  22. package/dist/mobileTransformer/mobile-replay/transformer/types.d.ts +40 -0
  23. package/dist/mobileTransformer/mobile-replay/transformer/wireframeStyle.d.ts +16 -0
  24. package/dist/mobileTransformer/mobile-replay/transformer/wireframeStyle.js +197 -0
  25. package/dist/mobileTransformer/utils.d.ts +1 -0
  26. package/dist/mobileTransformer/utils.js +5 -0
  27. package/dist/monitors/http-tools/GqlErrorValidator.js +4 -3
  28. package/dist/pageVisit/HttpEventManager.js +2 -2
  29. package/dist/sessionRecorder/SessionRecorder.js +7 -4
  30. package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +23 -3
  31. package/dist/sessionRecorder/types.d.ts +1 -1
  32. package/dist/utils/piiRedactor.js +15 -2
  33. package/dist/utils/piiRedactor.test.d.ts +1 -0
  34. package/ios/IOSPocEmitter.h +7 -0
  35. package/ios/IOSPocEmitter.m +33 -0
  36. package/noibu-react-native.podspec +50 -0
  37. package/package.json +17 -4
  38. package/android/.gitignore +0 -13
package/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ All notable changes of the noibu-react-native SDK release series are documented in this file using
4
+ the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
5
+
6
+ ## 0.2.13
7
+
8
+ ### Alpha support for iOS Session Replay in React Native
9
+
10
+ Implemented functionality that enables session replay support for iOS in React Native. Session videos are essential for
11
+ diagnosing errors. A video of an error occurring gives unique insight into the customer experience, and may help you
12
+ identify the step, field, button, or process that triggers the error.
13
+
14
+ ### Add support for customizable PII redaction fields
15
+
16
+ Implemented functionality to allow custom exact and fuzzy fields for PII redaction, configurable via ClientConfig. Added
17
+ corresponding tests to validate redaction logic and ensure compatibility with default and custom field configurations.
18
+ Refactored redaction logic to use dynamically retrieved configurations for better flexibility.
19
+
20
+ For more details on how to configure the SDK, please refer to
21
+ the [README.md - Configuration](./README.md#configuration).
package/README.md CHANGED
@@ -72,6 +72,9 @@ That's it! First time the module is set up, it runs an init and starts listening
72
72
  - `@property [blockedElements] {string[]}` - lets you specify component ids to be ignored by SDK when collecting error information
73
73
  - `@property [enableHttpDataCollection] {boolean}` - indicates whether SDK should collect HTTP information like headers or body from requests
74
74
  - `@property [listOfUrlsToCollectHttpDataFrom] {string[]}` - is an allow list of URLs to allow HTTP data collection from, works best with `enableHttpDataCollection` enabled
75
+ - `@property [httpPiiBlockingPatterns] {RegExp[]}` - allows you to specify RegEx patterns for what PII information should be removed from JSON request and response data for the value in a key value pair
76
+ - `@property [fuzzyFieldsToRedact] {string[]}` - allows you to specify fuzzy strings for what PII information should be removed from JSON request and response data based on the key in a key value pair
77
+ - `@property [exactFieldsToRedact] {string[]}` - allows you to specify strict strings for what PII information should be removed from JSON request and response data based on the key in a key value pair
75
78
 
76
79
  Example:
77
80
 
@@ -81,6 +84,72 @@ setupNoibu({
81
84
  enableHttpDataCollection: true,
82
85
  listOfUrlsToCollectHttpDataFrom: ['https://react-native-app.myshop.com/backend', 'https://example.com/some-path/'],
83
86
  blockedElements: ['sensitive-info'],
87
+ httpPiiBlockingPatterns: [
88
+ // Match credit cards [https://www.regular-expressions.info/creditcard.html]
89
+ // Visa
90
+ /\b4\d{12}(?:\d{3})?\b/g,
91
+
92
+ // MasterCard
93
+ /\b(?:5[1-5]\d{2}|222[1-9]|22[3-9]\d|2[3-6]\d{2}|27[01]\d|2720)\d{12}\b/g,
94
+
95
+ // Amex
96
+ /\b3[47]\d{13}\b/g,
97
+
98
+ // Diners Club
99
+ /\b3(?:0[0-5]|[68]\d)\d{11}\b/g,
100
+
101
+ // Discover
102
+ /\b6(?:011|5\d{2})\d{12}\b/g,
103
+
104
+ // JCB
105
+ /\b(?:2131|1800|35\d{3})\d{11}\b/g,
106
+
107
+ // Emails [https://www.regular-expressions.info/email.html]
108
+ /\b[a-z0-9!#$%&'*+/=?^_‘{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_‘{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\b/g,
109
+
110
+ // US SSN with or without dashes
111
+ // [https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s12.html]
112
+ /\b(?!000|666)[0-8]\d{2}[-.● ]?(?!00)\d{2}[-.● ]?(?!0000)\d{4}\b/g,
113
+
114
+ // Canadian SIN with or without dashes [https://regexpattern.com/social-insurance-number-ca]
115
+ /\b(\d{3}[-.● ]?\d{3}[-.● ]?\d{3})\b/g,
116
+
117
+ // International phone numbers
118
+ // [https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s03.html]
119
+ /\+(?:\d●?){6,14}\d\b/g,
120
+
121
+ // US/Canada phone numbers
122
+ // [https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s02.html]
123
+ /(\b|\+)?(1[-.● ]?)?\(?(\d{3})\)?[-.● ]?(\d{3})[-.● ]?(\d{4})\b/g,
124
+ ],
125
+ fuzzyFieldsToRedact: [
126
+ 'password',
127
+ 'address',
128
+ 'credit',
129
+ 'postal',
130
+ 'token',
131
+ 'phone',
132
+ 'mobile',
133
+ 'expiry',
134
+ 'account',
135
+ 'email',
136
+ ],
137
+ exactFieldsToRedact: [
138
+ 'firstname',
139
+ 'lastname',
140
+ 'street',
141
+ 'fullname',
142
+ 'creditcard',
143
+ 'postcode',
144
+ 'zipcode',
145
+ 'city',
146
+ 'town',
147
+ 'county',
148
+ 'cc',
149
+ 'cardtype',
150
+ 'cardnumber',
151
+ 'email',
152
+ ],
84
153
  });
85
154
  ```
86
155
 
@@ -21,6 +21,9 @@ export default class ClientConfig extends Singleton {
21
21
  readonly listOfUrlsToCollectHttpDataFrom: CustomerConfig['listOfUrlsToCollectHttpDataFrom'];
22
22
  readonly enableHttpDataCollection: CustomerConfig['enableHttpDataCollection'];
23
23
  readonly blockedElements: CustomerConfig['blockedElements'];
24
+ readonly httpPiiBlockingPatterns: CustomerConfig['httpPiiBlockingPatterns'];
25
+ readonly fuzzyFieldsToRedact: CustomerConfig['fuzzyFieldsToRedact'];
26
+ readonly exactFieldsToRedact: CustomerConfig['exactFieldsToRedact'];
24
27
  private alreadyPostingError;
25
28
  /** Error handling for constructor */
26
29
  handleConstructorError(noibuErrorURL?: string, customerConfig?: CustomerConfig): void;
@@ -67,6 +67,9 @@ class ClientConfig extends Singleton {
67
67
  this.listOfUrlsToCollectHttpDataFrom = customerConfig.listOfUrlsToCollectHttpDataFrom;
68
68
  this.enableHttpDataCollection = customerConfig.enableHttpDataCollection;
69
69
  this.blockedElements = customerConfig.blockedElements;
70
+ this.httpPiiBlockingPatterns = customerConfig.httpPiiBlockingPatterns;
71
+ this.fuzzyFieldsToRedact = customerConfig.fuzzyFieldsToRedact;
72
+ this.exactFieldsToRedact = customerConfig.exactFieldsToRedact;
70
73
  // sets up this.browserId, this.isClientDisabled, this.pageVisitSeq
71
74
  this.configurationPromise = this._setupStorageVars();
72
75
  }
@@ -4,7 +4,7 @@ import { NoSeqNumSlidingMessage, RetryQueueWSMessage } from '../types/Metroplex'
4
4
  /**
5
5
  * Grab the video recorder type based on the device we run the app on.
6
6
  */
7
- export declare function getVideoRecorderType(): Promise<VideoRecorder>;
7
+ export declare function getVideoRecorderType(): Promise<VideoRecorder.RRWeb | VideoRecorder.AndroidNative>;
8
8
  /**
9
9
  * Implements rolling window of specified size,
10
10
  * but only makes a cut once array length exceeds 150%.
@@ -22,9 +22,6 @@ function getVideoRecorderType() {
22
22
  if (Platform.OS === 'android') {
23
23
  return 'AndroidNative';
24
24
  }
25
- if (Platform.OS === 'ios') {
26
- return 'IOSNative';
27
- }
28
25
  return 'RRWeb'; // should never happen
29
26
  });
30
27
  }
@@ -250,7 +247,7 @@ class MetroplexSocket extends Singleton {
250
247
  return;
251
248
  }
252
249
  this.currentConnectionAttempts += 1;
253
- this.socket = new WebSocket(this.connectionURL, undefined, {
250
+ this.socket = new WebSocket(this.connectionURL, [], {
254
251
  headers: {
255
252
  'User-Agent': yield getUserAgent(), // must pass useragent explicitly
256
253
  },
@@ -701,7 +698,16 @@ class MetroplexSocket extends Singleton {
701
698
  const data = response.substring(prefix.length);
702
699
  const success = /^\d{6}$/.test(data);
703
700
  if (this.helpCodeCb) {
704
- this.helpCodeCb({ detail: { success, data } });
701
+ const event = {
702
+ detail: data,
703
+ bubbles: false,
704
+ cancelable: false,
705
+ cancelBubble: false,
706
+ };
707
+ Object.defineProperty(event, 'detail', {
708
+ get: () => ({ success, data }),
709
+ });
710
+ this.helpCodeCb(event);
705
711
  }
706
712
  return true;
707
713
  }
package/dist/constants.js CHANGED
@@ -24,7 +24,7 @@ const CONTENT_TYPE = 'content-type';
24
24
  * Gets the script id from the cookie object, returns default if cannot be found
25
25
  */
26
26
  function GET_SCRIPT_ID() {
27
- return "1.0.104-rn-sdk-0.2.12" ;
27
+ return "1.0.104-rn-sdk-0.2.14" ;
28
28
  }
29
29
  /**
30
30
  * Gets the max metro recon number
@@ -0,0 +1,10 @@
1
+ import { eventWithTime } from './rrweb';
2
+ import { ErrorObject } from 'ajv';
3
+ import { mobileEventWithTime } from './mobile.types';
4
+ export declare function validateFromMobile(data: unknown): {
5
+ isValid: boolean;
6
+ errors: ErrorObject[] | null | undefined;
7
+ };
8
+ export declare function transformEventToWeb(event: unknown, validateTransformation?: boolean): eventWithTime;
9
+ export declare function transformToWeb(mobileData: (eventWithTime | mobileEventWithTime)[]): eventWithTime[];
10
+ export declare function validateAgainstWebSchema(data: unknown): boolean;
@@ -0,0 +1,57 @@
1
+ import Ajv from 'ajv';
2
+ import mobileSchema from './schema/mobile/rr-mobile-schema.json.js';
3
+ import webSchema from './schema/web/rr-web-schema.json.js';
4
+ import { makeFullEvent, makeIncrementalEvent, makeMetaEvent, makeCustomEvent } from './transformer/transformers.js';
5
+
6
+ //import { captureException, captureMessage } from '@sentry/react'
7
+ //@ts-ignore
8
+ const ajv = new Ajv({
9
+ //@ts-ignore
10
+ allowUnionTypes: true,
11
+ }); // options can be passed, e.g. {allErrors: true}
12
+ const transformers = {
13
+ 2: makeFullEvent,
14
+ 3: makeIncrementalEvent,
15
+ 4: makeMetaEvent,
16
+ 5: makeCustomEvent,
17
+ };
18
+ ajv.compile(mobileSchema);
19
+ const webSchemaValidator = ajv.compile(webSchema);
20
+ function couldBeEventWithTime(x) {
21
+ return (typeof x === 'object' && x !== null && 'type' in x && 'timestamp' in x);
22
+ }
23
+ function transformEventToWeb(event, validateTransformation) {
24
+ try {
25
+ if (couldBeEventWithTime(event)) {
26
+ const transformer = transformers[event.type];
27
+ if (transformer) {
28
+ const transformed = transformer(event);
29
+ if (validateTransformation) ;
30
+ return transformed;
31
+ }
32
+ else {
33
+ //captureMessage(`No type in event`, { extra: { event } })
34
+ console.error('No type in event: ', event);
35
+ }
36
+ }
37
+ }
38
+ catch (e) {
39
+ //captureException(e, { extra: { event } })
40
+ console.error('Exception captured: ', event);
41
+ }
42
+ return event;
43
+ }
44
+ function validateAgainstWebSchema(data) {
45
+ const validationResult = webSchemaValidator(data);
46
+ if (!validationResult) {
47
+ // we are passing all data through this validation now and don't know how safe the schema is
48
+ // captureMessage('transformation did not match schema', {
49
+ // extra: { data, errors: webSchemaValidator.errors },
50
+ // });
51
+ console.error('transformation did not match schema', data, webSchemaValidator.errors);
52
+ }
53
+ //@ts-ignore
54
+ return validationResult;
55
+ }
56
+
57
+ export { transformEventToWeb, validateAgainstWebSchema };
@@ -0,0 +1,312 @@
1
+ import { customEvent, EventType, IncrementalSource, removedNodeMutation } from './rrweb';
2
+ export declare enum NodeType {
3
+ Document = 0,
4
+ DocumentType = 1,
5
+ Element = 2,
6
+ Text = 3,
7
+ CDATA = 4,
8
+ Comment = 5
9
+ }
10
+ export type documentNode = {
11
+ type: NodeType.Document;
12
+ childNodes: serializedNodeWithId[];
13
+ compatMode?: string;
14
+ };
15
+ export type documentTypeNode = {
16
+ type: NodeType.DocumentType;
17
+ name: string;
18
+ publicId: string;
19
+ systemId: string;
20
+ };
21
+ export type attributes = {
22
+ [key: string]: string | number | true | null;
23
+ };
24
+ export type elementNode = {
25
+ type: NodeType.Element;
26
+ tagName: string;
27
+ attributes: attributes;
28
+ childNodes: serializedNodeWithId[];
29
+ isSVG?: true;
30
+ needBlock?: boolean;
31
+ isCustom?: true;
32
+ };
33
+ export type textNode = {
34
+ type: NodeType.Text;
35
+ textContent: string;
36
+ isStyle?: true;
37
+ };
38
+ export type cdataNode = {
39
+ type: NodeType.CDATA;
40
+ textContent: '';
41
+ };
42
+ export type commentNode = {
43
+ type: NodeType.Comment;
44
+ textContent: string;
45
+ };
46
+ export type serializedNode = (documentNode | documentTypeNode | elementNode | textNode | cdataNode | commentNode) & {
47
+ rootId?: number;
48
+ isShadowHost?: boolean;
49
+ isShadow?: boolean;
50
+ };
51
+ export type serializedNodeWithId = serializedNode & {
52
+ id: number;
53
+ };
54
+ export type MobileNodeType = 'text' | 'image' | 'screenshot' | 'rectangle' | 'placeholder' | 'web_view' | 'input' | 'div' | 'radio_group' | 'status_bar' | 'navigation_bar';
55
+ export type MobileStyles = {
56
+ /**
57
+ * @description maps to CSS color. Accepts any valid CSS color value. Expects a #RGB value e.g. #000 or #000000
58
+ */
59
+ color?: string;
60
+ /**
61
+ * @description maps to CSS background-color. Accepts any valid CSS color value. Expects a #RGB value e.g. #000 or #000000
62
+ */
63
+ backgroundColor?: string;
64
+ /**
65
+ * @description if provided this will be used as a base64 encoded image source for the backgroundImage css property, with no other attributes it is assumed to be a PNG
66
+ */
67
+ backgroundImage?: string;
68
+ /**
69
+ * @description can be used alongside the background image property to specify how the image is rendered. Accepts a subset of the valid values for CSS background-size property. If not provided (and backgroundImage is present) defaults to 'auto'
70
+ */
71
+ backgroundSize?: 'contain' | 'cover' | 'auto';
72
+ /**
73
+ * @description if borderWidth is present, then border style is assumed to be solid
74
+ */
75
+ borderWidth?: string | number;
76
+ /**
77
+ * @description if borderRadius is present, then border style is assumed to be solid
78
+ */
79
+ borderRadius?: string | number;
80
+ /**
81
+ * @description if borderColor is present, then border style is assumed to be solid
82
+ */
83
+ borderColor?: string;
84
+ /**
85
+ * @description vertical alignment with respect to its parent
86
+ */
87
+ verticalAlign?: 'top' | 'bottom' | 'center';
88
+ /**
89
+ * @description horizontal alignment with respect to its parent
90
+ */
91
+ horizontalAlign?: 'left' | 'right' | 'center';
92
+ /**
93
+ * @description maps to CSS font-size. Accepts any valid CSS font-size value. Expects a number (treated as pixels) or a string that is a number followed by px e.g. 16px
94
+ */
95
+ fontSize?: string | number;
96
+ /**
97
+ * @description maps to CSS font-family. Accepts any valid CSS font-family value.
98
+ */
99
+ fontFamily?: string;
100
+ /**
101
+ * @description maps to CSS padding-left. Expects a number (treated as pixels) or a string that is a number followed by px e.g. 16px
102
+ */
103
+ paddingLeft?: string | number;
104
+ /**
105
+ * @description maps to CSS padding-right. Expects a number (treated as pixels) or a string that is a number followed by px e.g. 16px
106
+ */
107
+ paddingRight?: string | number;
108
+ /**
109
+ * @description maps to CSS padding-top. Expects a number (treated as pixels) or a string that is a number followed by px e.g. 16px
110
+ */
111
+ paddingTop?: string | number;
112
+ /**
113
+ * @description maps to CSS padding-bottom. Expects a number (treated as pixels) or a string that is a number followed by px e.g. 16px
114
+ */
115
+ paddingBottom?: string | number;
116
+ };
117
+ type wireframeBase = {
118
+ id: number;
119
+ /**
120
+ * @description x and y are the top left corner of the element, if they are present then the element is absolutely positioned, if they are not present this is equivalent to setting them to 0
121
+ */
122
+ x?: number;
123
+ y?: number;
124
+ width: number | '100vw';
125
+ height: number;
126
+ childWireframes?: wireframe[];
127
+ type: MobileNodeType;
128
+ style?: MobileStyles;
129
+ };
130
+ export type wireframeInputBase = wireframeBase & {
131
+ type: 'input';
132
+ /**
133
+ * @description for several attributes we technically only care about true or absent as values. They are represented as bare attributes in HTML <input disabled>. When true that attribute is added to the HTML element, when absent that attribute is not added to the HTML element. When false or absent they are not added to the element.
134
+ */
135
+ disabled: boolean;
136
+ };
137
+ export type wireframeCheckBox = wireframeInputBase & {
138
+ inputType: 'checkbox';
139
+ /**
140
+ * @description for several attributes we technically only care about true or absent as values. They are represented as bare attributes in HTML <input checked>. When true that attribute is added to the HTML element, when absent that attribute is not added to the HTML element. When false or absent they are not added to the element.
141
+ */
142
+ checked: boolean;
143
+ label?: string;
144
+ };
145
+ export type wireframeToggle = wireframeInputBase & {
146
+ inputType: 'toggle';
147
+ checked: boolean;
148
+ label?: string;
149
+ };
150
+ export type wireframeRadioGroup = wireframeBase & {
151
+ type: 'radio_group';
152
+ };
153
+ export type wireframeRadio = wireframeInputBase & {
154
+ inputType: 'radio';
155
+ /**
156
+ * @description for several attributes we technically only care about true or absent as values. They are represented as bare attributes in HTML <input checked>. When true that attribute is added to the HTML element, when absent that attribute is not added to the HTML element. When false or absent they are not added to the element.
157
+ */
158
+ checked: boolean;
159
+ label?: string;
160
+ };
161
+ export type wireframeInput = wireframeInputBase & {
162
+ inputType: 'text' | 'password' | 'email' | 'number' | 'search' | 'tel' | 'url';
163
+ value?: string;
164
+ };
165
+ export type wireframeSelect = wireframeInputBase & {
166
+ inputType: 'select';
167
+ value?: string;
168
+ options?: string[];
169
+ };
170
+ export type wireframeTextArea = wireframeInputBase & {
171
+ inputType: 'text_area';
172
+ value?: string;
173
+ };
174
+ export type wireframeButton = wireframeInputBase & {
175
+ inputType: 'button';
176
+ /**
177
+ * @description this is the text that is displayed on the button, if not sent then you must send childNodes with the button content
178
+ */
179
+ value?: string;
180
+ };
181
+ export type wireframeProgress = wireframeInputBase & {
182
+ inputType: 'progress';
183
+ /**
184
+ * @description This attribute specifies how much of the task that has been completed. It must be a valid floating point number between 0 and max, or between 0 and 1 if max is omitted. If there is no value attribute, the progress bar is indeterminate; this indicates that an activity is ongoing with no indication of how long it is expected to take. When bar style is rating this is the number of filled stars.
185
+ */
186
+ value?: number;
187
+ /**
188
+ * @description The max attribute, if present, must have a value greater than 0 and be a valid floating point number. The default value is 1. When bar style is rating this is the number of stars.
189
+ */
190
+ max?: number;
191
+ style?: MobileStyles & {
192
+ bar: 'horizontal' | 'circular' | 'rating';
193
+ };
194
+ };
195
+ export type wireframeInputComponent = wireframeCheckBox | wireframeRadio | wireframeInput | wireframeSelect | wireframeTextArea | wireframeButton | wireframeProgress | wireframeToggle;
196
+ export type wireframeText = wireframeBase & {
197
+ type: 'text';
198
+ text: string;
199
+ };
200
+ export type wireframeImage = wireframeBase & {
201
+ type: 'image';
202
+ /**
203
+ * @description this will be used as base64 encoded image source, with no other attributes it is assumed to be a PNG, if omitted a placeholder is rendered
204
+ */
205
+ base64?: string;
206
+ };
207
+ /**
208
+ * @description a screenshot behaves exactly like an image, but it is expected to be a screenshot of the screen at the time of the event, when sent as a mutation it must always attached to the root of the playback, when sent as an initial snapshot it must be sent as the first or only snapshot so that it attaches to the body of the playback
209
+ */
210
+ export type wireframeScreenshot = wireframeImage & {
211
+ type: 'screenshot';
212
+ };
213
+ export type wireframeRectangle = wireframeBase & {
214
+ type: 'rectangle';
215
+ };
216
+ export type wireframeWebView = wireframeBase & {
217
+ type: 'web_view';
218
+ url?: string;
219
+ };
220
+ export type wireframePlaceholder = wireframeBase & {
221
+ type: 'placeholder';
222
+ label?: string;
223
+ };
224
+ export type wireframeDiv = wireframeBase & {
225
+ type: 'div';
226
+ };
227
+ /**
228
+ * @description the status bar respects styling and positioning, but it is expected to be at the top of the screen with limited styling and no child elements
229
+ */
230
+ export type wireframeStatusBar = wireframeBase & {
231
+ type: 'status_bar';
232
+ };
233
+ /**
234
+ * @description the navigation bar respects styling and positioning, but it is expected to be at the bottom of the screen with limited styling and no child elements
235
+ */
236
+ export type wireframeNavigationBar = wireframeBase & {
237
+ type: 'navigation_bar';
238
+ };
239
+ export type wireframe = wireframeText | wireframeImage | wireframeScreenshot | wireframeRectangle | wireframeDiv | wireframeInputComponent | wireframeRadioGroup | wireframeWebView | wireframePlaceholder | wireframeStatusBar | wireframeNavigationBar;
240
+ export type fullSnapshotEvent = {
241
+ type: EventType.FullSnapshot;
242
+ data: {
243
+ /**
244
+ * @description This mimics the RRWeb full snapshot event type, except instead of reporting a serialized DOM it reports a wireframe representation of the screen.
245
+ */
246
+ wireframes: wireframe[];
247
+ initialOffset: {
248
+ top: number;
249
+ left: number;
250
+ };
251
+ };
252
+ };
253
+ export type incrementalSnapshotEvent = {
254
+ type: EventType.IncrementalSnapshot;
255
+ data: any;
256
+ } | MobileIncrementalSnapshotEvent;
257
+ export type MobileNodeMutation = {
258
+ parentId: number;
259
+ wireframe: wireframe;
260
+ };
261
+ export type MobileNodeMutationData = {
262
+ source: IncrementalSource.Mutation;
263
+ /**
264
+ * @description An update is implemented as a remove and then an add, so the updates array contains the ID of the removed node and the wireframe for the added node
265
+ */
266
+ updates?: MobileNodeMutation[];
267
+ adds?: MobileNodeMutation[];
268
+ /**
269
+ * @description A mobile remove is identical to a web remove
270
+ */
271
+ removes?: removedNodeMutation[];
272
+ };
273
+ export type MobileIncrementalSnapshotEvent = {
274
+ type: EventType.IncrementalSnapshot;
275
+ /**
276
+ * @description This sits alongside the RRWeb incremental snapshot event type, mobile replay can send any of the RRWeb incremental snapshot event types, which will be passed unchanged to the player - for example to send touch events. removed node mutations are passed unchanged to the player.
277
+ */
278
+ data: MobileNodeMutationData;
279
+ };
280
+ export type metaEvent = {
281
+ type: EventType.Meta;
282
+ data: {
283
+ href?: string;
284
+ width: number;
285
+ height: number;
286
+ };
287
+ };
288
+ export type keyboardEvent = {
289
+ type: EventType.Custom;
290
+ data: {
291
+ tag: 'keyboard';
292
+ payload: {
293
+ open: true;
294
+ styles?: MobileStyles;
295
+ /**
296
+ * @description x and y are the top left corner of the element, if they are present then the element is absolutely positioned, if they are not present then the keyboard is at the bottom of the screen
297
+ */
298
+ x?: number;
299
+ y?: number;
300
+ height: number;
301
+ width?: number;
302
+ } | {
303
+ open: false;
304
+ };
305
+ };
306
+ };
307
+ export type mobileEvent = fullSnapshotEvent | metaEvent | customEvent | incrementalSnapshotEvent | keyboardEvent;
308
+ export type mobileEventWithTime = mobileEvent & {
309
+ timestamp: number;
310
+ delay?: number;
311
+ };
312
+ export {};
@@ -0,0 +1,11 @@
1
+ var NodeType;
2
+ (function (NodeType) {
3
+ NodeType[NodeType["Document"] = 0] = "Document";
4
+ NodeType[NodeType["DocumentType"] = 1] = "DocumentType";
5
+ NodeType[NodeType["Element"] = 2] = "Element";
6
+ NodeType[NodeType["Text"] = 3] = "Text";
7
+ NodeType[NodeType["CDATA"] = 4] = "CDATA";
8
+ NodeType[NodeType["Comment"] = 5] = "Comment";
9
+ })(NodeType || (NodeType = {}));
10
+
11
+ export { NodeType };