@amplytools/react-native-amply-sdk 0.1.4 → 0.1.5

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.
@@ -15,7 +15,7 @@ buildscript {
15
15
  apply plugin: 'com.android.library'
16
16
  apply plugin: 'org.jetbrains.kotlin.android'
17
17
 
18
- def amplySdkVersion = project.findProperty('amplySdkVersion') ?: System.getenv('AMPLY_SDK_VERSION') ?: '0.1.10'
18
+ def amplySdkVersion = project.findProperty('amplySdkVersion') ?: System.getenv('AMPLY_SDK_VERSION') ?: '0.1.12'
19
19
  group = 'tools.amply'
20
20
  version = amplySdkVersion
21
21
 
@@ -203,7 +203,8 @@ class AmplyModule(reactContext: ReactApplicationContext) :
203
203
  private fun ensureLogEventCollection() {
204
204
  if (logEventsJob == null) {
205
205
  logEventsJob = scope.launch {
206
- client.logEvents.collectLatest { event ->
206
+ // Use collect (not collectLatest) to ensure all replayed logs are emitted
207
+ client.logEvents.collect { event ->
207
208
  emitOnSystemEvent(event.toWritableMap())
208
209
  }
209
210
  }
@@ -56,7 +56,7 @@ class DefaultAmplyClient(
56
56
  override val systemEvents: SharedFlow<EventEnvelope> = _systemEvents.asSharedFlow()
57
57
 
58
58
  private val _logEvents = MutableSharedFlow<EventEnvelope>(
59
- replay = 0,
59
+ replay = 64, // Replay buffer to capture init logs before JS collection starts
60
60
  extraBufferCapacity = 64,
61
61
  )
62
62
  override val logEvents: SharedFlow<EventEnvelope> = _logEvents.asSharedFlow()
@@ -70,21 +70,19 @@ class DefaultAmplyClient(
70
70
  "AmplyReactNative",
71
71
  "Initializing Amply with appId=${options.appId} apiKeyPublic=${options.apiKeyPublic.takeIf { it.isNotEmpty() } ?: "<empty>"}"
72
72
  )
73
- val instance = withContext(Dispatchers.Default) {
74
- Amply(config, application)
75
- }
76
73
 
77
- // Set log level from config
74
+ // Set log level and listener BEFORE creating instance so initialization logs are captured
78
75
  val effectiveLogLevel = options.getEffectiveLogLevel()
79
- instance.setLogLevel(effectiveLogLevel.toString())
76
+ tools.amply.sdk.logging.Logger.setLevel(effectiveLogLevel.toString())
77
+ android.util.Log.i("AmplyReactNative", "Pre-init log level set to: $effectiveLogLevel")
80
78
 
81
- // Set up log listener to emit logs to JS
82
- instance.setLogListener(object : LogListener {
79
+ // Set up log listener BEFORE instance creation to capture all init logs
80
+ tools.amply.sdk.logging.Logger.setListener(object : LogListener {
83
81
  override fun onLog(entry: LogEntry) {
84
82
  val envelope = EventEnvelope(
85
83
  id = null,
86
84
  name = "DebugLog",
87
- type = "system",
85
+ type = "log",
88
86
  timestamp = entry.timestamp,
89
87
  properties = buildMap {
90
88
  put("level", entry.level.toString())
@@ -102,6 +100,10 @@ class DefaultAmplyClient(
102
100
  }
103
101
  })
104
102
 
103
+ val instance = withContext(Dispatchers.Default) {
104
+ Amply(config, application)
105
+ }
106
+
105
107
  ensureSystemEventsListener(instance)
106
108
  amplyInstance = instance
107
109
  createdInstance = true
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'AmplyReactNative'
3
- s.version = '0.1.0-alpha.0'
3
+ s.version = '0.1.0-alpha.1'
4
4
  s.summary = 'React Native bridge for Amply SDK'
5
5
  s.homepage = 'https://github.com/amply/amply-react-native'
6
6
  s.license = { :type => 'MIT' }
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
16
16
  s.dependency 'React-RCTFabric'
17
17
 
18
18
  # Amply KMP SDK from CocoaPods
19
- s.dependency 'AmplySDK', '~> 0.1.10'
19
+ s.dependency 'AmplySDK', '~> 0.1.12'
20
20
 
21
21
  s.libraries = 'c++'
22
22
  s.pod_target_xcconfig = {
@@ -44,9 +44,7 @@ static NSString* AmplyLogLevelToString(AmplyLogLevel level) {
44
44
  return @"none";
45
45
  }
46
46
 
47
- // Note: ASDKLogListener is not yet available in KMP SDK iOS XCFramework
48
- // Logging support will be enabled when the KMP SDK iOS exports these APIs
49
- @interface Amply : NativeAmplyModuleSpecBase <NativeAmplyModuleSpec, ASDKDeepLinkListener, ASDKSystemEventsListener>
47
+ @interface Amply : NativeAmplyModuleSpecBase <NativeAmplyModuleSpec, ASDKDeepLinkListener, ASDKSystemEventsListener, ASDKLogListener>
50
48
  @property (nonatomic, strong) ASDKAmply *amplyInstance;
51
49
  @property (nonatomic, assign) BOOL deepLinkListenerRegistered;
52
50
  @property (nonatomic, assign) BOOL systemEventsListenerRegistered;
@@ -63,6 +61,9 @@ RCT_EXPORT_MODULE()
63
61
  reject:(RCTPromiseRejectBlock)reject
64
62
  {
65
63
  @try {
64
+ // Clear any existing log listener from previous instance (prevents crash on hot reload)
65
+ [[ASDKLogger shared] setListenerListener:nil];
66
+
66
67
  NSString *appId = config.appId();
67
68
  NSString *apiKeyPublic = config.apiKeyPublic();
68
69
  NSString *apiKeySecret = config.apiKeySecret();
@@ -101,10 +102,7 @@ RCT_EXPORT_MODULE()
101
102
 
102
103
  ASDKAmplyConfig *amplyConfig = [configBuilder build];
103
104
 
104
- // Create Amply instance
105
- self.amplyInstance = [[ASDKAmply alloc] initWithConfig:amplyConfig];
106
-
107
- // Parse debug and logLevel options
105
+ // Parse debug and logLevel options BEFORE creating instance
108
106
  std::optional<bool> debugOpt = config.debug();
109
107
  BOOL debug = debugOpt.has_value() && debugOpt.value();
110
108
  NSString *logLevelStr = config.logLevel();
@@ -118,13 +116,15 @@ RCT_EXPORT_MODULE()
118
116
  self.currentLogLevel = AmplyLogLevelNone;
119
117
  }
120
118
 
119
+ // Set log level and listener BEFORE creating Amply instance to capture init logs
121
120
  if (self.currentLogLevel != AmplyLogLevelNone) {
122
- RCTLogInfo(@"[AmplyReactNative] Debug logging enabled at level: %@", AmplyLogLevelToString(self.currentLogLevel));
121
+ RCTLogInfo(@"[AmplyReactNative] Setting log level to: %@ BEFORE instance creation", AmplyLogLevelToString(self.currentLogLevel));
122
+ [[ASDKLogger shared] setLevelLevel:AmplyLogLevelToString(self.currentLogLevel)];
123
+ [[ASDKLogger shared] setListenerListener:self];
123
124
  }
124
125
 
125
- // TODO: Enable when KMP SDK iOS exports setLogLevel and setLogListener
126
- // [self.amplyInstance setLogLevelLevel:AmplyLogLevelToString(self.currentLogLevel)];
127
- // [self registerLogListenerInternal];
126
+ // Create Amply instance (this triggers initialization and config fetch)
127
+ self.amplyInstance = [[ASDKAmply alloc] initWithConfig:amplyConfig];
128
128
 
129
129
  // Register system events listener
130
130
  [self registerSystemEventsListenerInternal];
@@ -394,10 +394,12 @@ RCT_EXPORT_MODULE()
394
394
  {
395
395
  self.currentLogLevel = AmplyLogLevelFromString(level);
396
396
  RCTLogInfo(@"[AmplyReactNative] Log level set to: %@", level);
397
- // TODO: Enable when KMP SDK iOS exports setLogLevel
398
- // if (self.amplyInstance) {
399
- // [self.amplyInstance setLogLevelLevel:level];
400
- // }
397
+ [[ASDKLogger shared] setLevelLevel:level];
398
+
399
+ // Ensure log listener is registered when enabling logging
400
+ if (self.currentLogLevel != AmplyLogLevelNone) {
401
+ [[ASDKLogger shared] setListenerListener:self];
402
+ }
401
403
  }
402
404
 
403
405
  - (NSString *)getLogLevel
@@ -461,6 +463,8 @@ RCT_EXPORT_MODULE()
461
463
  - (void)dealloc
462
464
  {
463
465
  [[NSNotificationCenter defaultCenter] removeObserver:self];
466
+ // Clear log listener to prevent crash when Logger tries to call deallocated object
467
+ [[ASDKLogger shared] setListenerListener:nil];
464
468
  }
465
469
 
466
470
  #pragma mark - ASDKSystemEventsListener
@@ -479,9 +483,41 @@ RCT_EXPORT_MODULE()
479
483
  [self emitOnSystemEvent:payload];
480
484
  }
481
485
 
482
- // TODO: Enable ASDKLogListener when KMP SDK iOS exports logging APIs
483
- // #pragma mark - ASDKLogListener
484
- // - (void)onLogEntry:(ASDKLogEntry *)entry { ... }
486
+ #pragma mark - ASDKLogListener
487
+
488
+ - (void)onLogEntry:(ASDKLogEntry *)entry
489
+ {
490
+ // Convert log level to string
491
+ NSString *levelString = @"unknown";
492
+ if (entry.level == ASDKLogLevel.debug) {
493
+ levelString = @"debug";
494
+ } else if (entry.level == ASDKLogLevel.info) {
495
+ levelString = @"info";
496
+ } else if (entry.level == ASDKLogLevel.warn) {
497
+ levelString = @"warn";
498
+ } else if (entry.level == ASDKLogLevel.error) {
499
+ levelString = @"error";
500
+ } else if (entry.level == ASDKLogLevel.none) {
501
+ levelString = @"none";
502
+ }
503
+
504
+ NSMutableDictionary *properties = [NSMutableDictionary dictionary];
505
+ properties[@"level"] = levelString;
506
+ properties[@"category"] = entry.category ?: @"";
507
+ properties[@"message"] = entry.message ?: @"";
508
+ if (entry.details) {
509
+ properties[@"details"] = entry.details;
510
+ }
511
+
512
+ NSDictionary *payload = @{
513
+ @"name": @"DebugLog",
514
+ @"type": @"log",
515
+ @"timestamp": @(entry.timestamp),
516
+ @"properties": properties
517
+ };
518
+
519
+ [self emitOnSystemEvent:payload];
520
+ }
485
521
 
486
522
  - (std::shared_ptr<TurboModule>)getTurboModule:(const ObjCTurboModule::InitParams &)params
487
523
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amplytools/react-native-amply-sdk",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "React Native SDK for Amply: Mobile SDK to orchestrate in-app experiences and campaigns remotely, without app releases",
5
5
  "license": "MIT",
6
6
  "repository": {