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

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 (43) hide show
  1. package/FTMobileReactNativeSDK.podspec +1 -1
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/ft/sdk/reactnative/FTMobileImpl.java +424 -5
  4. package/android/src/main/java/com/ft/sdk/reactnative/FTRUMImpl.java +12 -0
  5. package/android/src/newarch/java/com/ft/sdk/reactnative/FTMobileModule.java +23 -1
  6. package/android/src/oldarch/java/com/ft/sdk/reactnative/FTMobileModule.java +24 -2
  7. package/ios/FTMobileReactNative.h +2 -2
  8. package/ios/FTMobileReactNative.m +358 -4
  9. package/ios/FTReactNativeRUM.m +9 -0
  10. package/lib/commonjs/ft_logger.js +5 -2
  11. package/lib/commonjs/ft_logger.js.map +1 -1
  12. package/lib/commonjs/ft_mobile_agent.js +142 -3
  13. package/lib/commonjs/ft_mobile_agent.js.map +1 -1
  14. package/lib/commonjs/ft_rum.js +40 -13
  15. package/lib/commonjs/ft_rum.js.map +1 -1
  16. package/lib/commonjs/ft_tracing.js.map +1 -1
  17. package/lib/commonjs/index.js +30 -0
  18. package/lib/commonjs/index.js.map +1 -1
  19. package/lib/commonjs/version.js +1 -1
  20. package/lib/commonjs/version.js.map +1 -1
  21. package/lib/module/ft_logger.js +5 -2
  22. package/lib/module/ft_logger.js.map +1 -1
  23. package/lib/module/ft_mobile_agent.js +142 -3
  24. package/lib/module/ft_mobile_agent.js.map +1 -1
  25. package/lib/module/ft_rum.js +39 -9
  26. package/lib/module/ft_rum.js.map +1 -1
  27. package/lib/module/ft_tracing.js.map +1 -1
  28. package/lib/module/index.js +3 -3
  29. package/lib/module/index.js.map +1 -1
  30. package/lib/module/version.js +1 -1
  31. package/lib/module/version.js.map +1 -1
  32. package/lib/typescript/ft_mobile_agent.d.ts +140 -2
  33. package/lib/typescript/ft_rum.d.ts +24 -0
  34. package/lib/typescript/index.d.ts +3 -3
  35. package/lib/typescript/version.d.ts +1 -1
  36. package/package.json +1 -1
  37. package/src/ft_logger.tsx +6 -2
  38. package/src/ft_mobile_agent.tsx +217 -8
  39. package/src/ft_rum.tsx +66 -9
  40. package/src/ft_tracing.tsx +21 -2
  41. package/src/index.tsx +6 -5
  42. package/src/version.ts +1 -1
  43. package/android/src/main/java/com/ft/sdk/InnerClassProxy.java +0 -8
@@ -12,8 +12,281 @@
12
12
  #import <React/RCTConvert.h>
13
13
  #import <FTMobileSDK/FTThreadDispatchManager.h>
14
14
  #import <FTMobileSDK/FTConstants.h>
15
+ #import <FTMobileSDK/FTJSONUtil.h>
16
+ #import <FTMobileSDK/FTRemoteConfigModel+Private.h>
17
+
18
+ static NSString *const FTRemoteConfigCallbackEvent = @"ft_remote_config_callback";
19
+
15
20
  @implementation FTMobileReactNative
21
+ {
22
+ BOOL _hasListeners;
23
+ BOOL _remoteConfigurationEnabled;
24
+ int _remoteConfigMiniUpdateInterval;
25
+ NSArray<NSDictionary *> *_remoteConfigOverrideRules;
26
+ }
27
+
16
28
  RCT_EXPORT_MODULE()
29
+
30
+ - (NSArray<NSString *> *)supportedEvents
31
+ {
32
+ return @[FTRemoteConfigCallbackEvent];
33
+ }
34
+
35
+ - (void)startObserving
36
+ {
37
+ _hasListeners = YES;
38
+ }
39
+
40
+ - (void)stopObserving
41
+ {
42
+ _hasListeners = NO;
43
+ }
44
+
45
+ - (NSDictionary *)remoteConfigResultWithSuccess:(BOOL)success
46
+ content:(NSDictionary<NSString *, id> *_Nullable)content
47
+ error:(NSError *_Nullable)error
48
+ triggerType:(NSString *)triggerType
49
+ model:(FTRemoteConfigModel *_Nullable)model
50
+ rules:(NSArray<NSDictionary *> *_Nullable)rules
51
+ {
52
+ // Use local rules if provided, otherwise use global rules
53
+ NSArray<NSDictionary *> *rulesToApply = rules ?: _remoteConfigOverrideRules;
54
+ NSArray<NSString *> *appliedRuleIds = @[];
55
+
56
+ if (model && content && rulesToApply.count > 0) {
57
+ appliedRuleIds = [self applyRemoteConfigOverrideRulesWithModel:model content:content rules:rulesToApply];
58
+ }
59
+
60
+ NSMutableDictionary *payload = [NSMutableDictionary dictionary];
61
+ payload[@"triggerType"] = triggerType;
62
+ payload[@"success"] = @(success);
63
+ payload[@"platform"] = @"ios";
64
+ payload[@"timestamp"] = @((long long)([[NSDate date] timeIntervalSince1970] * 1000));
65
+
66
+ // Overridden content after applying rules
67
+ if (model && appliedRuleIds.count > 0) {
68
+ NSDictionary *overriddenContent = [model toDictionary];
69
+ payload[@"rawJson"] = [FTJSONUtil convertToJsonData:overriddenContent];
70
+ payload[@"appliedOverrideRuleIds"] = appliedRuleIds;
71
+ } else if (content) {
72
+ payload[@"rawJson"] = [FTJSONUtil convertToJsonData:content];
73
+ }
74
+ if (error) {
75
+ payload[@"errorCode"] = @(error.code);
76
+ payload[@"errorMessage"] = error.localizedDescription ?: @"";
77
+ }
78
+ return payload;
79
+ }
80
+
81
+ - (void)emitAutoRemoteConfigEventWithSuccess:(BOOL)success
82
+ content:(NSDictionary<NSString *, id> *_Nullable)content
83
+ error:(NSError *_Nullable)error
84
+ model:(FTRemoteConfigModel *_Nullable)model
85
+ {
86
+ if (!_hasListeners) {
87
+ return;
88
+ }
89
+ [self sendEventWithName:FTRemoteConfigCallbackEvent
90
+ body:[self remoteConfigResultWithSuccess:success
91
+ content:content
92
+ error:error
93
+ triggerType:@"auto"
94
+ model:model
95
+ rules:nil]];
96
+ }
97
+
98
+ - (BOOL)isEqualValue:(id)value1 toValue:(id)value2 {
99
+ if (value1 == nil && value2 == nil) {
100
+ return YES;
101
+ }
102
+ if (value1 == nil || value2 == nil) {
103
+ return NO;
104
+ }
105
+
106
+ if ([value1 isKindOfClass:[NSString class]]) {
107
+ id normalizedValue1 = [self parsedJSONArrayIfNeeded:value1];
108
+ if (normalizedValue1 != value1) {
109
+ return [self isEqualValue:normalizedValue1 toValue:value2];
110
+ }
111
+ }
112
+
113
+ // Handle NSNumber comparison
114
+ if ([value1 isKindOfClass:[NSNumber class]] && [value2 isKindOfClass:[NSNumber class]]) {
115
+ return [value1 isEqualToNumber:value2];
116
+ }
117
+
118
+ // Handle NSString comparison
119
+ if ([value1 isKindOfClass:[NSString class]] && [value2 isKindOfClass:[NSString class]]) {
120
+ return [value1 isEqualToString:value2];
121
+ }
122
+
123
+ // Handle NSArray comparison
124
+ if ([value1 isKindOfClass:[NSArray class]] && [value2 isKindOfClass:[NSArray class]]) {
125
+ return [value1 isEqualToArray:value2];
126
+ }
127
+
128
+ // Handle NSDictionary comparison
129
+ if ([value1 isKindOfClass:[NSDictionary class]] && [value2 isKindOfClass:[NSDictionary class]]) {
130
+ return [value1 isEqualToDictionary:value2];
131
+ }
132
+
133
+ // For other types, use description comparison as fallback
134
+ return [[value1 description] isEqualToString:[value2 description]];
135
+ }
136
+
137
+ - (BOOL)matchesCustomKeyActual:(id)actualValue expected:(id)expectedValue {
138
+ if ([expectedValue isKindOfClass:[NSDictionary class]]) {
139
+ NSDictionary *rule = (NSDictionary *)expectedValue;
140
+ id containsValue = rule[@"contains"];
141
+ if (containsValue != nil) {
142
+ return [self containsValueInActual:actualValue expected:containsValue];
143
+ }
144
+ }
145
+ return [self isEqualValue:actualValue toValue:expectedValue];
146
+ }
147
+
148
+ - (BOOL)containsValueInActual:(id)actualValue expected:(id)expectedValue {
149
+ id normalizedActual = [actualValue isKindOfClass:[NSString class]]
150
+ ? [self parsedJSONArrayIfNeeded:actualValue]
151
+ : actualValue;
152
+ if (![normalizedActual isKindOfClass:[NSArray class]]) {
153
+ return [self isEqualValue:normalizedActual toValue:expectedValue];
154
+ }
155
+ NSArray *array = (NSArray *)normalizedActual;
156
+ return [array containsObject:expectedValue];
157
+ }
158
+
159
+ - (id)parsedJSONArrayIfNeeded:(NSString *)value {
160
+ if (!value) return nil;
161
+
162
+ NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
163
+ NSError *error = nil;
164
+ id object = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
165
+
166
+ if (!error && [object isKindOfClass:[NSArray class]]) {
167
+ return object;
168
+ }
169
+ return value;
170
+ }
171
+
172
+ - (NSArray<NSString *> *)applyRemoteConfigOverrideRulesWithModel:(FTRemoteConfigModel *_Nullable)model
173
+ content:(NSDictionary<NSString *, id> *_Nullable)content
174
+ rules:(NSArray<NSDictionary *> *)rules
175
+ {
176
+ if (!model || !content || rules.count == 0) {
177
+ return @[];
178
+ }
179
+ NSMutableArray<NSString *> *appliedRuleIds = [NSMutableArray array];
180
+ [rules enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull rule, NSUInteger idx, BOOL * _Nonnull stop) {
181
+ BOOL enabled = ![rule.allKeys containsObject:@"enabled"] || [RCTConvert BOOL:rule[@"enabled"]];
182
+ if (!enabled) {
183
+ return;
184
+ }
185
+ NSDictionary *match = [RCTConvert NSDictionary:rule[@"match"]];
186
+ NSDictionary *customKeys = [RCTConvert NSDictionary:match[@"customKeys"]];
187
+ NSDictionary *override = [RCTConvert NSDictionary:rule[@"override"]];
188
+
189
+ if (customKeys.count == 0 || override.count == 0) {
190
+ return;
191
+ }
192
+ __block BOOL matches = YES;
193
+ [customKeys enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stopKeys) {
194
+ id actualValue = [content valueForKey:[key description]];
195
+ if (![self matchesCustomKeyActual:actualValue expected:obj]) {
196
+ matches = NO;
197
+ *stopKeys = YES;
198
+ }
199
+ }];
200
+ if (!matches) {
201
+ return;
202
+ }
203
+
204
+ // Basic configuration properties
205
+ if ([override.allKeys containsObject:@"env"]) {
206
+ model.env = [RCTConvert NSString:override[@"env"]];
207
+ }
208
+ if ([override.allKeys containsObject:@"serviceName"]) {
209
+ model.serviceName = [RCTConvert NSString:override[@"serviceName"]];
210
+ }
211
+ if ([override.allKeys containsObject:@"autoSync"]) {
212
+ model.autoSync = @([RCTConvert double:override[@"autoSync"]]);
213
+ }
214
+ if ([override.allKeys containsObject:@"compressIntakeRequests"]) {
215
+ model.compressIntakeRequests = @([RCTConvert double:override[@"compressIntakeRequests"]]);
216
+ }
217
+ if ([override.allKeys containsObject:@"syncPageSize"]) {
218
+ model.syncPageSize = @([RCTConvert double:override[@"syncPageSize"]]);
219
+ }
220
+ if ([override.allKeys containsObject:@"syncSleepTime"]) {
221
+ model.syncSleepTime = @([RCTConvert double:override[@"syncSleepTime"]]);
222
+ }
223
+
224
+ // RUM configuration properties
225
+ if ([override.allKeys containsObject:@"rumSampleRate"]) {
226
+ model.rumSampleRate = @([RCTConvert double:override[@"rumSampleRate"]]);
227
+ }
228
+ if ([override.allKeys containsObject:@"rumSessionOnErrorSampleRate"]) {
229
+ model.rumSessionOnErrorSampleRate = @([RCTConvert double:override[@"rumSessionOnErrorSampleRate"]]);
230
+ }
231
+ if ([override.allKeys containsObject:@"rumEnableTraceUserAction"]) {
232
+ model.rumEnableTraceUserAction = @([RCTConvert double:override[@"rumEnableTraceUserAction"]]);
233
+ }
234
+ if ([override.allKeys containsObject:@"rumEnableTraceUserView"]) {
235
+ model.rumEnableTraceUserView = @([RCTConvert double:override[@"rumEnableTraceUserView"]]);
236
+ }
237
+ if ([override.allKeys containsObject:@"rumEnableTraceUserResource"]) {
238
+ model.rumEnableTraceUserResource = @([RCTConvert double:override[@"rumEnableTraceUserResource"]]);
239
+ }
240
+ if ([override.allKeys containsObject:@"rumEnableResourceHostIP"]) {
241
+ model.rumEnableResourceHostIP = @([RCTConvert double:override[@"rumEnableResourceHostIP"]]);
242
+ }
243
+ if ([override.allKeys containsObject:@"rumEnableTrackAppUIBlock"]) {
244
+ model.rumEnableTrackAppUIBlock = @([RCTConvert double:override[@"rumEnableTrackAppUIBlock"]]);
245
+ }
246
+ if ([override.allKeys containsObject:@"rumBlockDurationMs"]) {
247
+ model.rumBlockDurationMs = @([RCTConvert double:override[@"rumBlockDurationMs"]]);
248
+ }
249
+ if ([override.allKeys containsObject:@"rumEnableTrackAppCrash"]) {
250
+ model.rumEnableTrackAppCrash = @([RCTConvert double:override[@"rumEnableTrackAppCrash"]]);
251
+ }
252
+ if ([override.allKeys containsObject:@"rumEnableTrackAppANR"]) {
253
+ model.rumEnableTrackAppANR = @([RCTConvert double:override[@"rumEnableTrackAppANR"]]);
254
+ }
255
+ if ([override.allKeys containsObject:@"rumEnableTraceWebView"]) {
256
+ model.rumEnableTraceWebView = @([RCTConvert double:override[@"rumEnableTraceWebView"]]);
257
+ }
258
+ if ([override.allKeys containsObject:@"rumAllowWebViewHost"]) {
259
+ model.rumAllowWebViewHost = [RCTConvert NSArray:override[@"rumAllowWebViewHost"]];
260
+ }
261
+
262
+ // Trace configuration properties
263
+ if ([override.allKeys containsObject:@"traceSampleRate"]) {
264
+ model.traceSampleRate = @([RCTConvert double:override[@"traceSampleRate"]]);
265
+ }
266
+ if ([override.allKeys containsObject:@"traceEnableAutoTrace"]) {
267
+ model.traceEnableAutoTrace = @([RCTConvert double:override[@"traceEnableAutoTrace"]]);
268
+ }
269
+ if ([override.allKeys containsObject:@"traceType"]) {
270
+ model.traceType = [RCTConvert NSString:override[@"traceType"]];
271
+ }
272
+
273
+ // Log configuration properties
274
+ if ([override.allKeys containsObject:@"logSampleRate"]) {
275
+ model.logSampleRate = @([RCTConvert double:override[@"logSampleRate"]]);
276
+ }
277
+ if ([override.allKeys containsObject:@"logLevelFilters"]) {
278
+ model.logLevelFilters = [RCTConvert NSArray:override[@"logLevelFilters"]];
279
+ }
280
+ if ([override.allKeys containsObject:@"logEnableCustomLog"]) {
281
+ model.logEnableCustomLog = @([RCTConvert double:override[@"logEnableCustomLog"]]);
282
+ }
283
+
284
+ NSString *ruleId = [RCTConvert NSString:rule[@"id"]];
285
+ [appliedRuleIds addObject:ruleId.length > 0 ? ruleId : [NSString stringWithFormat:@"rule_%lu", (unsigned long)idx]];
286
+ }];
287
+ return appliedRuleIds;
288
+ }
289
+
17
290
  RCT_REMAP_METHOD(sdkConfig,
18
291
  context:(NSDictionary *)context
19
292
  findEventsWithResolver:(RCTPromiseResolveBlock)resolve
@@ -102,8 +375,30 @@ RCT_REMAP_METHOD(sdkConfig,
102
375
  }
103
376
  };
104
377
  }
105
- NSString *pkgInfo = [RCTConvert NSString:context[@"pkgInfo"]];
106
- [config addPkgInfo:@"reactnative" value:pkgInfo];
378
+ if ([context.allKeys containsObject:@"remoteConfiguration"]){
379
+ config.remoteConfiguration = [RCTConvert BOOL:context[@"remoteConfiguration"]];
380
+ }
381
+ if ([context.allKeys containsObject:@"remoteConfigMiniUpdateInterval"]){
382
+ config.remoteConfigMiniUpdateInterval = [RCTConvert int:context[@"remoteConfigMiniUpdateInterval"]];
383
+ }
384
+ _remoteConfigOverrideRules = [RCTConvert NSArray:context[@"remoteConfigOverrideRules"]];
385
+ _remoteConfigurationEnabled = config.remoteConfiguration;
386
+ _remoteConfigMiniUpdateInterval = config.remoteConfigMiniUpdateInterval;
387
+ if (config.remoteConfiguration) {
388
+ __weak typeof(self) weakSelf = self;
389
+ config.remoteConfigFetchCompletionBlock = ^FTRemoteConfigModel * _Nullable(BOOL success, NSError * _Nullable error, FTRemoteConfigModel * _Nullable model, NSDictionary<NSString *,id> * _Nullable content) {
390
+ __typeof(self) strongSelf = weakSelf;
391
+ if (!strongSelf) {
392
+ return nil;
393
+ }
394
+ NSArray<NSString *> *appliedRuleIds = [strongSelf applyRemoteConfigOverrideRulesWithModel:model content:content rules:strongSelf->_remoteConfigOverrideRules];
395
+ [strongSelf emitAutoRemoteConfigEventWithSuccess:success content:content error:error model:model];
396
+ if (appliedRuleIds.count > 0) {
397
+ return model;
398
+ }
399
+ return nil;
400
+ };
401
+ }
107
402
  [FTMobileAgent startWithConfigOptions:config];
108
403
  resolve(nil);
109
404
  }];
@@ -165,7 +460,7 @@ RCT_REMAP_METHOD(trackEventFromExtension,
165
460
  }else{
166
461
  resolve(nil);
167
462
  }
168
-
463
+
169
464
  }];
170
465
  }
171
466
  RCT_REMAP_METHOD(shutDown,
@@ -180,4 +475,63 @@ RCT_REMAP_METHOD(clearAllData,
180
475
  [FTMobileAgent clearAllData];
181
476
  resolve(nil);
182
477
  }
183
- @end
478
+ RCT_REMAP_METHOD(updateRemoteConfig,
479
+ updateRemoteConfig_findEventsWithResolver:(RCTPromiseResolveBlock)resolve
480
+ rejecter:(RCTPromiseRejectBlock)reject){
481
+ if (!_remoteConfigurationEnabled) {
482
+ reject(@"E_REMOTE_CONFIG_DISABLED", @"Remote configuration is not enabled.", nil);
483
+ return;
484
+ }
485
+ [FTMobileAgent updateRemoteConfigWithMiniUpdateInterval:_remoteConfigMiniUpdateInterval completion:^FTRemoteConfigModel * _Nullable(BOOL success, NSError * _Nullable error, FTRemoteConfigModel * _Nullable model, NSDictionary<NSString *,id> * _Nullable content) {
486
+ NSDictionary *result = [self remoteConfigResultWithSuccess:success content:content error:error triggerType:@"manual" model:model rules:nil];
487
+ if (success) {
488
+ resolve(result);
489
+ } else {
490
+ NSString *message = error.localizedDescription ?: @"Remote config update failed.";
491
+ reject(@"E_REMOTE_CONFIG_UPDATE_FAILED", message, error);
492
+ }
493
+ NSArray<NSString *> *appliedRuleIds = result[@"appliedOverrideRuleIds"];
494
+ if (appliedRuleIds.count > 0) {
495
+ return model;
496
+ }
497
+ return nil;
498
+ }];
499
+ }
500
+ RCT_REMAP_METHOD(updateRemoteConfigWithMiniUpdateInterval,
501
+ interval:(int)interval
502
+ rules:(NSArray *)rules
503
+ findEventsWithResolver:(RCTPromiseResolveBlock)resolve
504
+ rejecter:(RCTPromiseRejectBlock)reject){
505
+ if (!_remoteConfigurationEnabled) {
506
+ reject(@"E_REMOTE_CONFIG_DISABLED", @"Remote configuration is not enabled.", nil);
507
+ return;
508
+ }
509
+ __weak typeof(self) weakSelf = self;
510
+ [FTMobileAgent updateRemoteConfigWithMiniUpdateInterval:(NSInteger)interval completion:^FTRemoteConfigModel * _Nullable(BOOL success, NSError * _Nullable error, FTRemoteConfigModel * _Nullable model, NSDictionary<NSString *,id> * _Nullable content) {
511
+ __typeof(self) strongSelf = weakSelf;
512
+ if (!strongSelf) {
513
+ return nil;
514
+ }
515
+ NSArray<NSDictionary *> *rulesToApply = nil;
516
+ if (rules != nil && ![rules isKindOfClass:[NSNull class]]) {
517
+ rulesToApply = [RCTConvert NSArray:rules];
518
+ }
519
+ if (rulesToApply == nil || rulesToApply.count == 0) {
520
+ rulesToApply = strongSelf->_remoteConfigOverrideRules;
521
+ }
522
+ NSDictionary *result = [strongSelf remoteConfigResultWithSuccess:success content:content error:error triggerType:@"manual" model:model rules:rulesToApply];
523
+ if (success) {
524
+ resolve(result);
525
+ } else {
526
+ NSString *message = error.localizedDescription ?: @"Remote config update failed.";
527
+ reject(@"E_REMOTE_CONFIG_UPDATE_FAILED", message, error);
528
+ }
529
+ NSArray<NSString *> *appliedRuleIds = result[@"appliedOverrideRuleIds"];
530
+ if (appliedRuleIds.count > 0) {
531
+ return model;
532
+ }
533
+ return nil;
534
+ }];
535
+ }
536
+
537
+ @end
@@ -70,6 +70,15 @@ RCT_REMAP_METHOD(setConfig,
70
70
  if ([context.allKeys containsObject:@"rumCacheLimitCount"]) {
71
71
  rumConfig.rumCacheLimitCount = [RCTConvert int:context[@"rumCacheLimitCount"]];
72
72
  }
73
+ if ([context.allKeys containsObject:@"enableTraceWebView"]) {
74
+ rumConfig.enableTraceWebView = [RCTConvert BOOL:context[@"enableTraceWebView"]];
75
+ }
76
+ if ([context.allKeys containsObject:@"allowWebViewHost"]) {
77
+ rumConfig.allowWebViewHost = [RCTConvert NSArray:context[@"allowWebViewHost"]];
78
+ }
79
+ if ([context.allKeys containsObject:@"iosCrashMonitoringType"]) {
80
+ rumConfig.crashMonitoring = (FTCrashMonitorType)[RCTConvert int:context[@"iosCrashMonitoringType"]];
81
+ }
73
82
  #if DEBUG
74
83
  rumConfig.resourceUrlHandler = ^BOOL(NSURL * _Nonnull url) {
75
84
  return [FTReactNativeUtils filterBlackResource:url];
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.FTReactNativeLog = exports.FTLogStatus = exports.FTLogCacheDiscard = void 0;
7
7
  var _reactNative = require("react-native");
8
+ var _ft_mobile_agent = require("./ft_mobile_agent");
8
9
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
9
10
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
10
11
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
@@ -59,11 +60,13 @@ class FTReactNativeLogWrapper {
59
60
  * @param property log context (optional)
60
61
  */
61
62
  logging(content, logStatus, property) {
63
+ // Automatically merge bridge context properties with local properties
64
+ const mergedProperties = _ft_mobile_agent.bridgeContextManager.mergeWithLocalPropertiesSync(property);
62
65
  if (typeof logStatus === 'string') {
63
- return this.logger.logWithStatusString(content, logStatus.toString(), property);
66
+ return this.logger.logWithStatusString(content, logStatus.toString(), mergedProperties);
64
67
  }
65
68
  let enumLogStatus = logStatus;
66
- return this.logger.logging(content, enumLogStatus, property);
69
+ return this.logger.logging(content, enumLogStatus, mergedProperties);
67
70
  }
68
71
  }
69
72
  const FTReactNativeLog = exports.FTReactNativeLog = new FTReactNativeLogWrapper();
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_defineProperty","e","r","t","_toPropertyKey","Object","defineProperty","value","enumerable","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","FTLogStatus","exports","FTLogCacheDiscard","FTReactNativeLogWrapper","constructor","NativeModules","FTReactNativeLog","logConfig","config","logger","logging","content","logStatus","property","logWithStatusString","toString","enumLogStatus"],"sources":["ft_logger.tsx"],"sourcesContent":["import { NativeModules } from 'react-native';\n/**\n * Set log level.\n */\n export enum FTLogStatus {\n info, warning, error, critical, ok,\n };\n/**\n * Log discard method.\n */\n export enum FTLogCacheDiscard { discard, discardOldest };\n/**\n * Configure log output configuration.\n * @param sampleRate sampling rate\n * @param enableLinkRumData whether to link with RUM\n * @param enableCustomLog whether to enable custom logs\n * @param discardStrategy log discard strategy\n * @param logLevelFilters log level filter\n * @param globalContext custom global parameters\n * @param logCacheLimitCount get maximum log entry count limit [1000,), default 5000\n */\n export interface FTLogConfig{\n sampleRate?: number,\n enableLinkRumData?: boolean,\n enableCustomLog?: boolean,\n discardStrategy?: FTLogCacheDiscard,\n logLevelFilters?: Array<FTLogStatus>,\n globalContext?:object,\n logCacheLimitCount?: number\n };\n\n type FTReactNativeLogType = {\n /**\n *Configure log output configuration to enable log collection.\n */\n logConfig(config: FTLogConfig): Promise<void>;\n /**\n * Output log.\n * @param content log content\n * @param status log status\n * @param property log context (optional)\n */\n logging(content:String,logStatus:FTLogStatus,property?:object): Promise<void>;\n /**\n * Output log.\n * @param content log content\n * @param status log status\n * @param property log context (optional)\n */\n logWithStatusString(content:String,logStatus:String,property?:object): Promise<void>;\n };\n\n class FTReactNativeLogWrapper {\n private logger: FTReactNativeLogType = NativeModules.FTReactNativeLog;\n\n /**\n *Configure log output configuration to enable log collection.\n */\n logConfig(config:FTLogConfig): Promise<void>{\n return this.logger.logConfig(config);\n }\n\n /**\n * Output log.\n * @param content log content\n * @param status log status\n * @param property log context (optional)\n */\n logging(content:String,logStatus:FTLogStatus|String,property?:object): Promise<void>{\n if((typeof logStatus)==='string'){\n return this.logger.logWithStatusString(content,logStatus.toString(),property)\n }\n let enumLogStatus: FTLogStatus = logStatus as FTLogStatus;\n return this.logger.logging(content,enumLogStatus,property);\n }\n }\n export const FTReactNativeLog: FTReactNativeLogWrapper = new FTReactNativeLogWrapper();\n"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAA6C,SAAAC,gBAAAC,CAAA,EAAAC,CAAA,EAAAC,CAAA,YAAAD,CAAA,GAAAE,cAAA,CAAAF,CAAA,MAAAD,CAAA,GAAAI,MAAA,CAAAC,cAAA,CAAAL,CAAA,EAAAC,CAAA,IAAAK,KAAA,EAAAJ,CAAA,EAAAK,UAAA,MAAAC,YAAA,MAAAC,QAAA,UAAAT,CAAA,CAAAC,CAAA,IAAAC,CAAA,EAAAF,CAAA;AAAA,SAAAG,eAAAD,CAAA,QAAAQ,CAAA,GAAAC,YAAA,CAAAT,CAAA,uCAAAQ,CAAA,GAAAA,CAAA,GAAAA,CAAA;AAAA,SAAAC,aAAAT,CAAA,EAAAD,CAAA,2BAAAC,CAAA,KAAAA,CAAA,SAAAA,CAAA,MAAAF,CAAA,GAAAE,CAAA,CAAAU,MAAA,CAAAC,WAAA,kBAAAb,CAAA,QAAAU,CAAA,GAAAV,CAAA,CAAAc,IAAA,CAAAZ,CAAA,EAAAD,CAAA,uCAAAS,CAAA,SAAAA,CAAA,YAAAK,SAAA,yEAAAd,CAAA,GAAAe,MAAA,GAAAC,MAAA,EAAAf,CAAA;AAC7C;AACA;AACA;AAFA,IAGagB,WAAW,GAAAC,OAAA,CAAAD,WAAA,0BAAXA,WAAW;EAAXA,WAAW,CAAXA,WAAW;EAAXA,WAAW,CAAXA,WAAW;EAAXA,WAAW,CAAXA,WAAW;EAAXA,WAAW,CAAXA,WAAW;EAAXA,WAAW,CAAXA,WAAW;EAAA,OAAXA,WAAW;AAAA;AAEtB;AACF;AACA;AACA;AAFA,IAGaE,iBAAiB,GAAAD,OAAA,CAAAC,iBAAA,0BAAjBA,iBAAiB;EAAjBA,iBAAiB,CAAjBA,iBAAiB;EAAjBA,iBAAiB,CAAjBA,iBAAiB;EAAA,OAAjBA,iBAAiB;AAAA;AAA2B;AACzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASE;AAuBD,MAAMC,uBAAuB,CAAE;EAAAC,YAAA;IAAAvB,eAAA,iBACUwB,0BAAa,CAACC,gBAAgB;EAAA;EAEtE;AACF;AACA;EACGC,SAASA,CAACC,MAAkB,EAAgB;IAC1C,OAAO,IAAI,CAACC,MAAM,CAACF,SAAS,CAACC,MAAM,CAAC;EACtC;;EAEA;AACH;AACA;AACA;AACA;AACA;EACGE,OAAOA,CAACC,OAAc,EAACC,SAA4B,EAACC,QAAgB,EAAgB;IAClF,IAAI,OAAOD,SAAS,KAAI,QAAQ,EAAC;MAC/B,OAAO,IAAI,CAACH,MAAM,CAACK,mBAAmB,CAACH,OAAO,EAACC,SAAS,CAACG,QAAQ,CAAC,CAAC,EAACF,QAAQ,CAAC;IAC/E;IACA,IAAIG,aAA0B,GAAGJ,SAAwB;IACzD,OAAO,IAAI,CAACH,MAAM,CAACC,OAAO,CAACC,OAAO,EAACK,aAAa,EAACH,QAAQ,CAAC;EAC5D;AACF;AACO,MAAMP,gBAAyC,GAAAL,OAAA,CAAAK,gBAAA,GAAG,IAAIH,uBAAuB,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_ft_mobile_agent","_defineProperty","e","r","t","_toPropertyKey","Object","defineProperty","value","enumerable","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","FTLogStatus","exports","FTLogCacheDiscard","FTReactNativeLogWrapper","constructor","NativeModules","FTReactNativeLog","logConfig","config","logger","logging","content","logStatus","property","mergedProperties","bridgeContextManager","mergeWithLocalPropertiesSync","logWithStatusString","toString","enumLogStatus"],"sources":["ft_logger.tsx"],"sourcesContent":["import { NativeModules } from 'react-native';\nimport { bridgeContextManager } from './ft_mobile_agent';\n/**\n * Set log level.\n */\n export enum FTLogStatus {\n info, warning, error, critical, ok,\n };\n/**\n * Log discard method.\n */\n export enum FTLogCacheDiscard { discard, discardOldest };\n/**\n * Configure log output configuration.\n * @param sampleRate sampling rate\n * @param enableLinkRumData whether to link with RUM\n * @param enableCustomLog whether to enable custom logs\n * @param discardStrategy log discard strategy\n * @param logLevelFilters log level filter\n * @param globalContext custom global parameters\n * @param logCacheLimitCount get maximum log entry count limit [1000,), default 5000\n */\n export interface FTLogConfig{\n sampleRate?: number,\n enableLinkRumData?: boolean,\n enableCustomLog?: boolean,\n discardStrategy?: FTLogCacheDiscard,\n logLevelFilters?: Array<FTLogStatus>,\n globalContext?:object,\n logCacheLimitCount?: number\n };\n\n type FTReactNativeLogType = {\n /**\n *Configure log output configuration to enable log collection.\n */\n logConfig(config: FTLogConfig): Promise<void>;\n /**\n * Output log.\n * @param content log content\n * @param status log status\n * @param property log context (optional)\n */\n logging(content:String,logStatus:FTLogStatus,property?:object): Promise<void>;\n /**\n * Output log.\n * @param content log content\n * @param status log status\n * @param property log context (optional)\n */\n logWithStatusString(content:String,logStatus:String,property?:object): Promise<void>;\n };\n\n class FTReactNativeLogWrapper {\n private logger: FTReactNativeLogType = NativeModules.FTReactNativeLog;\n\n /**\n *Configure log output configuration to enable log collection.\n */\n logConfig(config:FTLogConfig): Promise<void>{\n return this.logger.logConfig(config);\n }\n\n /**\n * Output log.\n * @param content log content\n * @param status log status\n * @param property log context (optional)\n */\n logging(content:String,logStatus:FTLogStatus|String,property?:object): Promise<void>{\n // Automatically merge bridge context properties with local properties\n const mergedProperties = bridgeContextManager.mergeWithLocalPropertiesSync(property);\n \n if((typeof logStatus)==='string'){\n return this.logger.logWithStatusString(content,logStatus.toString(),mergedProperties)\n }\n let enumLogStatus: FTLogStatus = logStatus as FTLogStatus;\n return this.logger.logging(content,enumLogStatus,mergedProperties);\n }\n }\n export const FTReactNativeLog: FTReactNativeLogWrapper = new FTReactNativeLogWrapper();\n"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,gBAAA,GAAAD,OAAA;AAAyD,SAAAE,gBAAAC,CAAA,EAAAC,CAAA,EAAAC,CAAA,YAAAD,CAAA,GAAAE,cAAA,CAAAF,CAAA,MAAAD,CAAA,GAAAI,MAAA,CAAAC,cAAA,CAAAL,CAAA,EAAAC,CAAA,IAAAK,KAAA,EAAAJ,CAAA,EAAAK,UAAA,MAAAC,YAAA,MAAAC,QAAA,UAAAT,CAAA,CAAAC,CAAA,IAAAC,CAAA,EAAAF,CAAA;AAAA,SAAAG,eAAAD,CAAA,QAAAQ,CAAA,GAAAC,YAAA,CAAAT,CAAA,uCAAAQ,CAAA,GAAAA,CAAA,GAAAA,CAAA;AAAA,SAAAC,aAAAT,CAAA,EAAAD,CAAA,2BAAAC,CAAA,KAAAA,CAAA,SAAAA,CAAA,MAAAF,CAAA,GAAAE,CAAA,CAAAU,MAAA,CAAAC,WAAA,kBAAAb,CAAA,QAAAU,CAAA,GAAAV,CAAA,CAAAc,IAAA,CAAAZ,CAAA,EAAAD,CAAA,uCAAAS,CAAA,SAAAA,CAAA,YAAAK,SAAA,yEAAAd,CAAA,GAAAe,MAAA,GAAAC,MAAA,EAAAf,CAAA;AACzD;AACA;AACA;AAFA,IAGagB,WAAW,GAAAC,OAAA,CAAAD,WAAA,0BAAXA,WAAW;EAAXA,WAAW,CAAXA,WAAW;EAAXA,WAAW,CAAXA,WAAW;EAAXA,WAAW,CAAXA,WAAW;EAAXA,WAAW,CAAXA,WAAW;EAAXA,WAAW,CAAXA,WAAW;EAAA,OAAXA,WAAW;AAAA;AAEtB;AACF;AACA;AACA;AAFA,IAGaE,iBAAiB,GAAAD,OAAA,CAAAC,iBAAA,0BAAjBA,iBAAiB;EAAjBA,iBAAiB,CAAjBA,iBAAiB;EAAjBA,iBAAiB,CAAjBA,iBAAiB;EAAA,OAAjBA,iBAAiB;AAAA;AAA2B;AACzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASE;AAuBD,MAAMC,uBAAuB,CAAE;EAAAC,YAAA;IAAAvB,eAAA,iBACUwB,0BAAa,CAACC,gBAAgB;EAAA;EAEtE;AACF;AACA;EACGC,SAASA,CAACC,MAAkB,EAAgB;IAC1C,OAAO,IAAI,CAACC,MAAM,CAACF,SAAS,CAACC,MAAM,CAAC;EACtC;;EAEA;AACH;AACA;AACA;AACA;AACA;EACGE,OAAOA,CAACC,OAAc,EAACC,SAA4B,EAACC,QAAgB,EAAgB;IAClF;IACA,MAAMC,gBAAgB,GAAGC,qCAAoB,CAACC,4BAA4B,CAACH,QAAQ,CAAC;IAEpF,IAAI,OAAOD,SAAS,KAAI,QAAQ,EAAC;MAC/B,OAAO,IAAI,CAACH,MAAM,CAACQ,mBAAmB,CAACN,OAAO,EAACC,SAAS,CAACM,QAAQ,CAAC,CAAC,EAACJ,gBAAgB,CAAC;IACvF;IACA,IAAIK,aAA0B,GAAGP,SAAwB;IACzD,OAAO,IAAI,CAACH,MAAM,CAACC,OAAO,CAACC,OAAO,EAACQ,aAAa,EAACL,gBAAgB,CAAC;EACpE;AACF;AACO,MAAMR,gBAAyC,GAAAL,OAAA,CAAAK,gBAAA,GAAG,IAAIH,uBAAuB,CAAC,CAAC","ignoreList":[]}
@@ -3,12 +3,101 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.FTMobileReactNative = exports.FTDBCacheDiscard = exports.EnvType = void 0;
6
+ exports.bridgeContextManager = exports.FTMobileReactNative = exports.FTDBCacheDiscard = exports.EnvType = void 0;
7
7
  var _reactNative = require("react-native");
8
8
  var _version = require("./version");
9
+ var _BridgeContextManager;
9
10
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
10
11
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
11
12
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
13
+ /**
14
+ * Bridge context manager for managing shared properties across RUM and Logger modules
15
+ * This class provides a centralized way to store and retrieve global properties that will be
16
+ * automatically merged with local properties when making calls to RUM and Logger functions
17
+ */
18
+ class BridgeContextManager {
19
+ constructor() {
20
+ _defineProperty(this, "properties", new Map());
21
+ // Initialize with SDK version information
22
+ this.initializeSDKInfo();
23
+ }
24
+
25
+ /**
26
+ * Initialize SDK information properties
27
+ * @private
28
+ */
29
+ initializeSDKInfo() {
30
+ // Create sdk_bridge_info with version information
31
+ const sdkBridgeInfo = {
32
+ react_native: _version.version
33
+ };
34
+
35
+ // Set the sdk_bridge_info property
36
+ this.properties.set('sdk_bridge_info', JSON.stringify(sdkBridgeInfo));
37
+ }
38
+
39
+ /**
40
+ * Get singleton instance of BridgeContextManager
41
+ * @returns BridgeContextManager instance
42
+ */
43
+ static getInstance() {
44
+ if (!BridgeContextManager.instance) {
45
+ BridgeContextManager.instance = new BridgeContextManager();
46
+ }
47
+ return BridgeContextManager.instance;
48
+ }
49
+
50
+ /**
51
+ * Add bridge context properties that will be automatically merged with local properties
52
+ * @param properties Object containing key-value pairs
53
+ */
54
+ appendBridgeContext(properties) {
55
+ // Store properties locally in JavaScript
56
+ try {
57
+ // Store properties locally in JavaScript
58
+ Object.entries(properties).forEach(([key, value]) => {
59
+ this.properties.set(key, value);
60
+ });
61
+ } catch (error) {
62
+ console.warn('Failed to append bridge context:', error);
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Merge bridge context properties with local properties
68
+ * Bridge context properties take precedence over local properties
69
+ * @param localProperties Local properties to merge with bridge context properties
70
+ * @returns Merged properties object
71
+ */
72
+ mergeWithLocalPropertiesSync(localProperties) {
73
+ try {
74
+ const merged = {};
75
+
76
+ // First add local properties (if any)
77
+ if (localProperties) {
78
+ Object.assign(merged, localProperties);
79
+ }
80
+
81
+ // Then add bridge context properties (these will override local properties with same keys)
82
+ this.properties.forEach((value, key) => {
83
+ merged[key] = value;
84
+ });
85
+ return merged;
86
+ } catch (error) {
87
+ console.warn('Failed to merge bridge context with local properties:', error);
88
+ // Return empty object or only local properties on error
89
+ return localProperties ? {
90
+ ...localProperties
91
+ } : {};
92
+ }
93
+ }
94
+ }
95
+
96
+ // Internal bridge context manager - not exported
97
+ _BridgeContextManager = BridgeContextManager;
98
+ _defineProperty(BridgeContextManager, "instance", void 0);
99
+ const bridgeContextManager = exports.bridgeContextManager = BridgeContextManager.getInstance();
100
+
12
101
  /**
13
102
  * Environment.
14
103
  */
@@ -27,6 +116,40 @@ let FTDBCacheDiscard = exports.FTDBCacheDiscard = /*#__PURE__*/function (FTDBCac
27
116
  return FTDBCacheDiscard;
28
117
  }({});
29
118
  ;
119
+
120
+ /**
121
+ * Remote config override rule matching condition for custom keys. Supports exact match and contains match.
122
+ * For exact match, set the value directly, for example: "userid": "test_user", which means the rule will be applied when the custom key "userid" is exactly "test_user".
123
+ * For contains match, set the value as an object with a "contains" field, for example: "userid": { "contains": "test_user" }, which means the rule will be applied when the custom key "userid" contains the object "test_user".
124
+ */
125
+
126
+ /**
127
+ * Matching rules for remote config override
128
+ * Defines matching conditions using customKeys
129
+ */
130
+
131
+ /**
132
+ * Values that can be modified by remote config override rules.
133
+ * These values will adjust the fetched remote configuration before it is applied.
134
+ */
135
+
136
+ /**
137
+ * Remote config override rules .
138
+ * Adjust the fetched remote configuration before application.
139
+ */
140
+
141
+ /**
142
+ * Final result of the remote config update
143
+ * @param triggerType the type of remote config update trigger, auto or manual
144
+ * @param success whether the remote config update was successful
145
+ * @param platform the platform of the device, ios or android
146
+ * @param timestamp the timestamp when the remote config update was triggered
147
+ * @param rawJson the final remote config update result, in JSON string format
148
+ * @param errorCode the error code if the remote config update failed, may be null if the update was successful
149
+ * @param errorMessage the error message if the remote config update failed, may be null if the update was successful
150
+ * @param appliedOverrideRuleIds the list of override rule IDs applied in this remote config update, may be null if no rules were applied
151
+ */
152
+
30
153
  /**
31
154
  * Configure SDK startup parameters.
32
155
  * @param serverUrl data reporting address, deprecated, use [datakitUrl] instead
@@ -48,17 +171,20 @@ let FTDBCacheDiscard = exports.FTDBCacheDiscard = /*#__PURE__*/function (FTDBCac
48
171
  * @param dbDiscardStrategy db data discard strategy
49
172
  * @param dataModifier data modifier, modify individual fields {key:value}, after setting, the SDK will replace the original value with the set value according to the key
50
173
  * @param lineDataModifier data modifier, modify single data {"measurement":measurement,"data":{key:value}}, after setting, the SDK will replace the original value with the set value according to the key
51
- */
174
+ * @param remoteConfiguration Set whether to enable remote dynamic configuration
175
+ * @param remoteConfigMiniUpdateInterval Set remote dynamic configuration minimum update interval, unit seconds, default 12*60*60
176
+ * @param remoteConfigOverrideRules Remote config override rules .Adjust the fetched remote configuration before application.
177
+ */
52
178
 
53
179
  class FTMobileReactNativeWrapper {
54
180
  constructor() {
55
181
  _defineProperty(this, "sdk", _reactNative.NativeModules.FTMobileReactNative);
182
+ _defineProperty(this, "emitter", new _reactNative.NativeEventEmitter(_reactNative.NativeModules.FTMobileReactNative));
56
183
  }
57
184
  sdkConfig(config) {
58
185
  if (config.serverUrl != null && config.serverUrl.length > 0 && config.datakitUrl == null) {
59
186
  config.datakitUrl = config.serverUrl;
60
187
  }
61
- config.pkgInfo = _version.version;
62
188
  return this.sdk.sdkConfig(config);
63
189
  }
64
190
  bindRUMUserData(userId, userName, userEmail, extra) {
@@ -88,6 +214,19 @@ class FTMobileReactNativeWrapper {
88
214
  clearAllData() {
89
215
  return this.sdk.clearAllData();
90
216
  }
217
+ appendBridgeContext(properties) {
218
+ // Use bridgeContextManager to store properties in JavaScript and send to native SDK
219
+ bridgeContextManager.appendBridgeContext(properties);
220
+ }
221
+ updateRemoteConfig() {
222
+ return this.sdk.updateRemoteConfig();
223
+ }
224
+ updateRemoteConfigWithMiniUpdateInterval(interval, rules) {
225
+ return this.sdk.updateRemoteConfigWithMiniUpdateInterval(interval, rules);
226
+ }
227
+ addRemoteConfigListener(listener) {
228
+ return this.emitter.addListener('ft_remote_config_callback', listener);
229
+ }
91
230
  }
92
231
  const FTMobileReactNative = exports.FTMobileReactNative = new FTMobileReactNativeWrapper();
93
232
  //# sourceMappingURL=ft_mobile_agent.js.map