@truewatchtech/react-native-mobile 0.3.15-alpha.1

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 (102) hide show
  1. package/FTMobileReactNativeSDK.podspec +22 -0
  2. package/LICENSE +201 -0
  3. package/README.md +37 -0
  4. package/android/.project +17 -0
  5. package/android/.settings/org.eclipse.buildship.core.prefs +13 -0
  6. package/android/build.gradle +183 -0
  7. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  8. package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  9. package/android/gradle.properties +5 -0
  10. package/android/gradlew +185 -0
  11. package/android/gradlew.bat +89 -0
  12. package/android/local.properties +8 -0
  13. package/android/src/main/AndroidManifest.xml +4 -0
  14. package/android/src/main/AndroidManifestNew.xml +4 -0
  15. package/android/src/main/java/com/ft/sdk/InnerClassProxy.java +8 -0
  16. package/android/src/main/java/com/ft/sdk/reactnative/FTLogImpl.java +133 -0
  17. package/android/src/main/java/com/ft/sdk/reactnative/FTMobileImpl.java +198 -0
  18. package/android/src/main/java/com/ft/sdk/reactnative/FTRUMImpl.java +267 -0
  19. package/android/src/main/java/com/ft/sdk/reactnative/FTTraceImpl.java +89 -0
  20. package/android/src/main/java/com/ft/sdk/reactnative/utils/ReactNativeUtils.java +59 -0
  21. package/android/src/newarch/java/com/ft/sdk/reactnative/FTLogModule.java +39 -0
  22. package/android/src/newarch/java/com/ft/sdk/reactnative/FTMobileModule.java +69 -0
  23. package/android/src/newarch/java/com/ft/sdk/reactnative/FTRUMModule.java +84 -0
  24. package/android/src/newarch/java/com/ft/sdk/reactnative/FTTraceModule.java +34 -0
  25. package/android/src/oldarch/java/com/ft/sdk/reactnative/FTLogModule.java +36 -0
  26. package/android/src/oldarch/java/com/ft/sdk/reactnative/FTMobileModule.java +69 -0
  27. package/android/src/oldarch/java/com/ft/sdk/reactnative/FTRUMModule.java +70 -0
  28. package/android/src/oldarch/java/com/ft/sdk/reactnative/FTTraceModule.java +30 -0
  29. package/android/src/rnpost74/java/com/ft/sdk/reactnative/FTMobilePackage.java +71 -0
  30. package/android/src/rnpre74/java/com/ft/sdk/reactnative/FTMobilePackage.java +33 -0
  31. package/ios/.idea/.name +1 -0
  32. package/ios/.idea/ios.iml +2 -0
  33. package/ios/.idea/modules.xml +8 -0
  34. package/ios/.idea/vcs.xml +6 -0
  35. package/ios/.idea/xcode.xml +4 -0
  36. package/ios/FTMobileReactNative.h +18 -0
  37. package/ios/FTMobileReactNative.m +183 -0
  38. package/ios/FTReactNativeLog.h +18 -0
  39. package/ios/FTReactNativeLog.m +60 -0
  40. package/ios/FTReactNativeRUM.h +19 -0
  41. package/ios/FTReactNativeRUM.m +173 -0
  42. package/ios/FTReactNativeTrace.h +20 -0
  43. package/ios/FTReactNativeTrace.m +58 -0
  44. package/ios/FTReactNativeUtils.h +16 -0
  45. package/ios/FTReactNativeUtils.m +32 -0
  46. package/ios/FtMobileAgent.xcodeproj/project.pbxproj +293 -0
  47. package/ios/FtMobileAgent.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
  48. package/ios/FtMobileAgent.xcodeproj/project.xcworkspace/xcuserdata/Brandon.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  49. package/ios/FtMobileAgent.xcodeproj/project.xcworkspace/xcuserdata/Brandon.xcuserdatad/xcschemes/xcschememanagement.plist +5 -0
  50. package/ios/FtMobileAgent.xcodeproj/xcuserdata/Brandon.xcuserdatad/xcschemes/FtMobileAgent.xcscheme +56 -0
  51. package/ios/FtMobileAgent.xcodeproj/xcuserdata/Brandon.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  52. package/ios/RCTVersion.h +8 -0
  53. package/lib/commonjs/ft_logger.js +70 -0
  54. package/lib/commonjs/ft_logger.js.map +1 -0
  55. package/lib/commonjs/ft_mobile_agent.js +93 -0
  56. package/lib/commonjs/ft_mobile_agent.js.map +1 -0
  57. package/lib/commonjs/ft_rum.js +143 -0
  58. package/lib/commonjs/ft_rum.js.map +1 -0
  59. package/lib/commonjs/ft_tracing.js +61 -0
  60. package/lib/commonjs/ft_tracing.js.map +1 -0
  61. package/lib/commonjs/index.js +138 -0
  62. package/lib/commonjs/index.js.map +1 -0
  63. package/lib/commonjs/rum/FTRumActionTracking.js +214 -0
  64. package/lib/commonjs/rum/FTRumActionTracking.js.map +1 -0
  65. package/lib/commonjs/rum/FTRumErrorTracking.js +99 -0
  66. package/lib/commonjs/rum/FTRumErrorTracking.js.map +1 -0
  67. package/lib/commonjs/version.js +9 -0
  68. package/lib/commonjs/version.js.map +1 -0
  69. package/lib/module/ft_logger.js +64 -0
  70. package/lib/module/ft_logger.js.map +1 -0
  71. package/lib/module/ft_mobile_agent.js +88 -0
  72. package/lib/module/ft_mobile_agent.js.map +1 -0
  73. package/lib/module/ft_rum.js +138 -0
  74. package/lib/module/ft_rum.js.map +1 -0
  75. package/lib/module/ft_tracing.js +56 -0
  76. package/lib/module/ft_tracing.js.map +1 -0
  77. package/lib/module/index.js +8 -0
  78. package/lib/module/index.js.map +1 -0
  79. package/lib/module/rum/FTRumActionTracking.js +206 -0
  80. package/lib/module/rum/FTRumActionTracking.js.map +1 -0
  81. package/lib/module/rum/FTRumErrorTracking.js +92 -0
  82. package/lib/module/rum/FTRumErrorTracking.js.map +1 -0
  83. package/lib/module/version.js +3 -0
  84. package/lib/module/version.js.map +1 -0
  85. package/lib/typescript/ft_logger.d.ts +52 -0
  86. package/lib/typescript/ft_mobile_agent.d.ts +123 -0
  87. package/lib/typescript/ft_rum.d.ts +200 -0
  88. package/lib/typescript/ft_tracing.d.ts +47 -0
  89. package/lib/typescript/index.d.ts +7 -0
  90. package/lib/typescript/rum/FTRumActionTracking.d.ts +15 -0
  91. package/lib/typescript/rum/FTRumErrorTracking.d.ts +11 -0
  92. package/lib/typescript/version.d.ts +1 -0
  93. package/package.json +167 -0
  94. package/scripts/replace-react-require.js +52 -0
  95. package/src/ft_logger.tsx +77 -0
  96. package/src/ft_mobile_agent.tsx +162 -0
  97. package/src/ft_rum.tsx +247 -0
  98. package/src/ft_tracing.tsx +79 -0
  99. package/src/index.tsx +17 -0
  100. package/src/rum/FTRumActionTracking.tsx +232 -0
  101. package/src/rum/FTRumErrorTracking.tsx +110 -0
  102. package/src/version.ts +2 -0
@@ -0,0 +1,232 @@
1
+ import React from 'react'
2
+ import { FTReactNativeRUM } from '../ft_rum';
3
+ const FT_ENABLE_TRACK = 'ft-enable-track';
4
+ const FT_EXTRA_PROPERTY = 'ft-extra-property';
5
+ export class FTRumActionTracking {
6
+ private static isTracking = false
7
+ private static preActionTimestamp = Number.MIN_VALUE;
8
+ private static originalMemo = React.memo;
9
+ private static originalJsx = null;
10
+ private static originalCreateElement = React.createElement;
11
+
12
+ private static patchCreateElementFunction = (
13
+ originalFunction: typeof React.createElement,
14
+ [element, props, ...rest]: Parameters<typeof React.createElement>
15
+ ): ReturnType<typeof React.createElement> => {
16
+ if (
17
+ props &&
18
+ typeof (props as Record<string, unknown>).onPress === 'function'
19
+ ) {
20
+ const originalOnPress = (props as Record<string, unknown>) // eslint-disable-next-line @typescript-eslint/ban-types
21
+ .onPress as Function;
22
+ (props as Record<string, unknown>).onPress = (...args: any[]) => {
23
+ FTRumActionTracking.interceptOnPress(
24
+ ...args
25
+ );
26
+ return originalOnPress(...args);
27
+ };
28
+
29
+ (props as Record<
30
+ string,
31
+ unknown
32
+ >).__FT_INTERNAL_ORIGINAL_ON_PRESS__ = originalOnPress;
33
+ }
34
+ return originalFunction(element, props, ...rest);
35
+ };
36
+ static startTracking(): void {
37
+ if (FTRumActionTracking.isTracking) {
38
+ return
39
+ }
40
+ const original = React.createElement
41
+ React.createElement = (
42
+ ...args: Parameters<typeof React.createElement>
43
+ ): any => {
44
+ return this.patchCreateElementFunction(original, args);
45
+ };
46
+ try {
47
+ const jsxRuntime = getJsxRuntime();
48
+ const originaljsx = jsxRuntime.jsx;
49
+ this.originalJsx = originaljsx;
50
+ jsxRuntime.jsx = (
51
+ ...args: Parameters<typeof React.createElement>
52
+ ): ReturnType<typeof React.createElement> => {
53
+ return this.patchCreateElementFunction(originaljsx, args);
54
+ };
55
+ } catch (e) {
56
+
57
+ }
58
+
59
+ const originalMemo = React.memo;
60
+ React.memo = (
61
+ component: any,
62
+ propsAreEqual?: (prevProps: any, newProps: any) => boolean
63
+ ) => {
64
+ return originalMemo(component, (prev, next) => {
65
+ if (!next.onPress || !prev.onPress) {
66
+ return propsAreEqual
67
+ ? propsAreEqual(prev, next)
68
+ : areObjectShallowEqual(prev, next);
69
+ }
70
+
71
+ const { onPress: _prevOnPress, ...partialPrevProps } = prev;
72
+ const prevProps = {
73
+ ...partialPrevProps,
74
+ onPress: prev.__FT_INTERNAL_ORIGINAL_ON_PRESS__
75
+ };
76
+
77
+ const { onPress: _nextOnPress, ...partialNextProps } = next;
78
+ const nextProps = {
79
+ ...partialNextProps,
80
+ onPress: next.__FT_INTERNAL_ORIGINAL_ON_PRESS__
81
+ };
82
+
83
+ return propsAreEqual
84
+ ? propsAreEqual(prevProps, nextProps)
85
+ : areObjectShallowEqual(nextProps, prevProps);
86
+ });
87
+ };
88
+ FTRumActionTracking.isTracking = true
89
+ }
90
+ static stopTracking() {
91
+ React.createElement = this.originalCreateElement;
92
+ React.memo = this.originalMemo;
93
+ FTRumActionTracking.isTracking = false;
94
+ if (this.originalJsx) {
95
+ const jsxRuntime = getJsxRuntime();
96
+ jsxRuntime.jsx = this.originalJsx;
97
+ this.originalJsx = null;
98
+ }
99
+ }
100
+
101
+ private static interceptOnPress(...args: any[]): void {
102
+ if (args.length > 0 && args[0] && args[0]._targetInst) {
103
+ const currentTime = Date.now()
104
+ const timestampDifference = Math.abs(Date.now() - FTRumActionTracking.preActionTimestamp)
105
+ if (timestampDifference > 10) {
106
+ const targetNode = args[0]._targetInst
107
+ this.handleTargetEvent(targetNode)
108
+ FTRumActionTracking.preActionTimestamp = currentTime
109
+ }
110
+ }
111
+ }
112
+
113
+ private static handleTargetEvent(targetNode: any | null) {
114
+ if (targetNode) {
115
+ const enable = FTRumActionTracking.findActionEnableTrack(targetNode);
116
+ if (enable) {
117
+ const extraProperty = FTRumActionTracking.findActionProperty(targetNode);
118
+ const elementTypeName = FTRumActionTracking.resolveActionName(targetNode);
119
+ if (elementTypeName) {
120
+ let jsonObject = null
121
+ if (extraProperty) {
122
+ try {
123
+ jsonObject = JSON.parse(extraProperty)
124
+ } catch (error) {
125
+ console.warn(`Error parsing JSON string ${extraProperty}:`,error);
126
+ }
127
+ }
128
+ if (jsonObject){
129
+ FTReactNativeRUM.startAction(elementTypeName, 'click',jsonObject);
130
+ }else{
131
+ FTReactNativeRUM.startAction(elementTypeName, 'click');
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+
138
+ private static resolveActionName(targetNode:any): string | null {
139
+ const accessibilityLabel = targetNode.memoizedProps?.accessibilityLabel
140
+ if(accessibilityLabel != null){
141
+ return accessibilityLabel;
142
+ }
143
+ const accessibilityRole = targetNode.memoizedProps?.accessibilityRole;
144
+ let subTitle = '';
145
+ let children = targetNode.memoizedProps?.children;
146
+ while (children){
147
+ if(Array.isArray(children) && children.length>0 && children[0]){
148
+ children = children[0];
149
+ }else if(typeof children === 'object' && children.props && children.props.children){
150
+ children = children.props.children;
151
+ }else if(typeof children === 'string'){
152
+ subTitle = children;
153
+ children = null;
154
+ }else{
155
+ children = null;
156
+ }
157
+ }
158
+ let elementTypeName = accessibilityRole;
159
+ if(!accessibilityRole){
160
+ let elementType = targetNode.elementType;
161
+ if (typeof elementType === "string") {
162
+ elementTypeName = elementType
163
+ } else if (elementType && typeof elementType.name === "string") {
164
+ elementTypeName = elementType.name
165
+ }
166
+ }
167
+ if(elementTypeName){
168
+ return '['+elementTypeName+']'+subTitle;
169
+ }
170
+ return null;
171
+
172
+ }
173
+ private static findActionProperty(targetNode: any): string | null {
174
+ let currentNode = targetNode;
175
+ while (currentNode) {
176
+ const props = currentNode.memoizedProps;
177
+ if (props && props[FT_EXTRA_PROPERTY]) {
178
+ return props[FT_EXTRA_PROPERTY];
179
+ }
180
+ currentNode = currentNode.return;
181
+ }
182
+ return null;
183
+ }
184
+ private static findActionEnableTrack(targetNode: any): boolean {
185
+ let currentNode = targetNode;
186
+ let enable = true
187
+ while (currentNode) {
188
+ const props = currentNode.memoizedProps;
189
+ if (props && props[FT_ENABLE_TRACK]) {
190
+ enable = props[FT_ENABLE_TRACK] == "true";
191
+ break;
192
+ }
193
+ currentNode = currentNode.return;
194
+ }
195
+ return enable;
196
+ }
197
+ }
198
+
199
+ const areObjectShallowEqual = (
200
+ objectA: Record<string, unknown> | undefined | null,
201
+ objectB: Record<string, unknown> | undefined | null
202
+ ): boolean => {
203
+ if (!objectA || !objectB) {
204
+ return objectA === objectB;
205
+ }
206
+
207
+ const keys = Object.keys(objectA);
208
+ if (keys.length !== Object.keys(objectB).length) {
209
+ return false;
210
+ }
211
+ for (const key of keys) {
212
+ if (objectA[key] !== objectB[key]) {
213
+ return false;
214
+ }
215
+ }
216
+ return true;
217
+ };
218
+ const getJsxRuntime = () => {
219
+ // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
220
+ const [major, minor] = require('react/package.json').version.split('.');
221
+ // JSX Transform applies to > 16.14.0
222
+ if (Number(major)<=16&&Number(minor)<14) {
223
+ throw new Error('React version does not support new jsx transform');
224
+ }
225
+
226
+ // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
227
+ const jsxRuntime = require('react/jsx-runtime');
228
+ if (!jsxRuntime.jsx) {
229
+ throw new Error('React jsx runtime does not export new jsx transform');
230
+ }
231
+ return jsxRuntime;
232
+ };
@@ -0,0 +1,110 @@
1
+ import type { ErrorHandlerCallback } from 'react-native';
2
+ import { FTReactNativeRUM } from '../ft_rum';
3
+ const EMPTY_MESSAGE = 'Unknown Error';
4
+ const CONSOLE_ERROR = "console_error";
5
+
6
+ export class FTRumErrorTracking {
7
+ private static isTracking = false;
8
+
9
+ private static isInDefaultErrorHandler = false;
10
+
11
+ // Original error handler method
12
+ private static defaultErrorHandler: ErrorHandlerCallback = (_error: any, _isFatal?: boolean) => { }
13
+
14
+ // Original console error handler method
15
+ private static defaultConsoleError = (..._params: unknown[]) => { }
16
+
17
+ static startTracking(): void {
18
+ if(FTRumErrorTracking.isTracking){
19
+ return;
20
+ }
21
+ if (ErrorUtils) {
22
+ FTRumErrorTracking.defaultErrorHandler = ErrorUtils.getGlobalHandler;
23
+ FTRumErrorTracking.defaultConsoleError = console.error;
24
+ ErrorUtils.setGlobalHandler(FTRumErrorTracking.onGlobalError);
25
+ console.error = FTRumErrorTracking.onConsoleError;
26
+ FTRumErrorTracking.isTracking = true;
27
+ }
28
+ }
29
+ static onGlobalError(error: any, isFatal?: boolean): void {
30
+ const message = FTRumErrorTracking.getErrorMessage(error);
31
+ const stacktrace = FTRumErrorTracking.getErrorStackTrace(error);
32
+ FTReactNativeRUM.addError(
33
+ stacktrace,
34
+ message
35
+ ).then(() => {
36
+ try {
37
+ FTRumErrorTracking.isInDefaultErrorHandler = true;
38
+ //Call the original error handler method
39
+ FTRumErrorTracking.defaultErrorHandler(error, isFatal);
40
+ } finally {
41
+ FTRumErrorTracking.isInDefaultErrorHandler = false;
42
+ }
43
+ });
44
+ }
45
+
46
+ static onConsoleError(...params: unknown[]): void {
47
+ if ( FTRumErrorTracking.isInDefaultErrorHandler) {
48
+ return;
49
+ }
50
+
51
+ let stack: string = '';
52
+ for (let i = 0; i < params.length; i += 1) {
53
+ const param = params[i];
54
+ const paramStack = FTRumErrorTracking.getErrorStackTrace(param);
55
+ if (paramStack != undefined && paramStack != '') {
56
+ stack = paramStack;
57
+ break;
58
+ }
59
+ }
60
+
61
+ const message = params.map((param) => {
62
+ if (typeof param === 'string') { return param; }
63
+ else { return FTRumErrorTracking.getErrorMessage(param); }
64
+ }).join(' ');
65
+
66
+
67
+ FTReactNativeRUM.addErrorWithType(
68
+ CONSOLE_ERROR,
69
+ stack,
70
+ message,
71
+ ).then(() => {
72
+ FTRumErrorTracking.defaultConsoleError.apply(console, params);
73
+ });
74
+
75
+ }
76
+ private static getErrorMessage(error: any | undefined): string {
77
+ let message = EMPTY_MESSAGE;
78
+ if (error == undefined || error === null) {
79
+ message = EMPTY_MESSAGE;
80
+ } else if (typeof error === 'object' && 'message' in error){
81
+ message = String(error.message);
82
+ } else {
83
+ message = String(error);
84
+ }
85
+
86
+ return message
87
+ }
88
+
89
+ private static getErrorStackTrace(error: any | undefined): string {
90
+ let stack = '';
91
+
92
+ if (error == undefined) {
93
+ stack = '';
94
+ } else if (typeof error === 'string') {
95
+ stack = '';
96
+ } else if ('componentStack' in error) {
97
+ stack = String(error.componentStack);
98
+ } else if ('stacktrace' in error) {
99
+ stack = String(error.stacktrace);
100
+ } else if ('stack' in error) {
101
+ stack = String(error.stack);
102
+ } else if (('sourceURL' in error) && ('line' in error) && ('column' in error)) {
103
+ stack = `at ${error.sourceURL}:${error.line}:${error.column}`;
104
+ }
105
+
106
+ return stack
107
+ }
108
+ }
109
+
110
+
package/src/version.ts ADDED
@@ -0,0 +1,2 @@
1
+ // generated by genversion
2
+ export const version = '0.3.15-alpha.1';