Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions ios/RNUsercentricsModule+TurboModule.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// RNUsercentricsModule+TurboModule.mm
// getTurboModule: implementation for RN 0.78+ (New Architecture).
// RCTTurboModule protocol requires C++ return type (shared_ptr<TurboModule>), hence Obj-C++.
//

#import <React/RCTBridgeModule.h>

#if RCT_NEW_ARCH_ENABLED

#import <ReactCommon/RCTTurboModule.h>

// Header generated by the app's codegen (ReactCodegen pod; path may vary by RN version)
#if __has_include(<ReactCodegen/RNUsercentricsModule/RNUsercentricsModule.h>)
#import <ReactCodegen/RNUsercentricsModule/RNUsercentricsModule.h>
#else
#import "RNUsercentricsModule/RNUsercentricsModule.h"
#endif
Comment on lines +13 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Fragile codegen header include 🐞 Bug ⛯ Reliability

The TurboModule ObjC++ file imports a codegen-generated header via either <ReactCodegen/...> or a
quoted include ("RNUsercentricsModule/..."). The podspec no longer adds explicit
React-Codegen/ReactCodegen header search paths and only injects codegen dependencies when
install_modules_dependencies is defined, so some new-arch builds can fail with missing-header
errors.
Agent Prompt
### Issue description
`RNUsercentricsModule+TurboModule.mm` requires a codegen header but the podspec no longer guarantees header search paths/dependencies unless `install_modules_dependencies` is defined and effective. This can lead to `file not found` build errors for new-arch consumers.

### Issue Context
Header locations differ across RN versions (`ReactCodegen` vs `React-Codegen`), and consumers may not always have the helper available (custom Podfiles/build setups).

### Fix Focus Areas
- ios/RNUsercentricsModule+TurboModule.mm[13-18]
- react-native-usercentrics.podspec[23-55]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


// RNUsercentricsModule is defined in Swift (RNUsercentricsModule.swift).
// Minimal declaration so the compiler accepts the category; the real implementation is in Swift.
@interface RNUsercentricsModule : NSObject
@end

@implementation RNUsercentricsModule (TurboModule)

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params {
return std::make_shared<facebook::react::NativeUsercentricsModuleSpecJSI>(params);
}
Comment on lines +27 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] The code returns std::make_sharedfacebook::react::NativeUsercentricsModuleSpecJSI(params). That generated C++/JSI type may not exist (name varies by RN/codegen). This will fail linking/compilation if the generated JSI class name or header differs. Actionable options: 1) Verify the exact generated C++ type name and include the correct generated header from codegen, or 2) if relying on an ObjC TurboModule wrapper, return an ObjCTurboModule-backed TurboModule (or nullptr) until the generated JSI class is available. At minimum, add a compile-time guard/comment and test building with RN 0.78/0.79 to confirm the correct symbol.

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
    (const facebook::react::ObjCTurboModule::InitParams &)params {
#if __has_include(<ReactCodegen/RNUsercentricsModule/RNUsercentricsModule.h>)
  return std::make_shared<facebook::react::NativeUsercentricsModuleSpecJSI>(params);
#else
  // Fallback for configurations where the generated JSI type is not available
  return nullptr;
#endif
}


@end

#endif // RCT_NEW_ARCH_ENABLED
24 changes: 17 additions & 7 deletions ios/RNUsercentricsModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import UIKit
import React

#if RCT_NEW_ARCH_ENABLED
#if canImport(RNUsercentricsModuleSpec)
#if canImport(ReactCodegen)
// RN ≥ 0.79: getTurboModule: implemented in RNUsercentricsModule+TurboModule.mm (do not import ReactCodegen in Swift — C++ module)
#elseif canImport(React_Codegen)
// RN 0.78
import React_Codegen
#elseif canImport(RNUsercentricsModuleSpec)
Comment on lines +8 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[REFACTORING] The preprocessor branch uses canImport(ReactCodegen) (no underscore) followed by canImport(React_Codegen). The module name historically used by RN codegen is 'React_Codegen' (with underscore). The top-level canImport(ReactCodegen) branch is ambiguous and only contains a comment (no import). Consider removing the canImport(ReactCodegen) check (or correct it) and consolidate logic so it's explicit which RN versions import which module. This avoids confusion and accidental dead branches during compilation.

#if RCT_NEW_ARCH_ENABLED
// RN ≥ 0.79: getTurboModule: implemented in RNUsercentricsModule+TurboModule.mm (do not import ReactCodegen in Swift — C++ module)
#if canImport(React_Codegen)
// RN 0.78
import React_Codegen
#elif canImport(RNUsercentricsModuleSpec)
// RN ≤ 0.77
import RNUsercentricsModuleSpec
#endif
#endif

// RN ≤ 0.77
import RNUsercentricsModuleSpec
#else
// RN ≥ 0.78
import React_Codegen
#endif
#endif

Expand Down Expand Up @@ -229,13 +231,21 @@ class RNUsercentricsModule: NSObject {

// MARK: - RCTBridgeModule & TurboModule Conformance
#if RCT_NEW_ARCH_ENABLED
#if canImport(React_Codegen)
// RN 0.78: codegen-generated protocol
extension RNUsercentricsModule: NativeUsercentricsModuleSpec {
func getTurboModule(jsInvoker: RCTJSInvoker) -> Any {
return self
}
}
#elseif canImport(RNUsercentricsModuleSpec)
// RN ≤ 0.77
extension RNUsercentricsModule: NativeUsercentricsSpec {
func getTurboModule(jsInvoker: RCTJSInvoker) -> Any {
return self
}
Comment on lines +234 to 246
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] The extension implements/declares conformance to NativeUsercentricsModuleSpec which does not match the generated protocol name in the project reference (NativeUsercentricsSpec). This will cause a compile-time error (type not found). Replace NativeUsercentricsModuleSpec with the correct generated protocol (NativeUsercentricsSpec) or detect the correct symbol via canImport and adapt accordingly. Also run a clean build to verify the generated module/protocol name for the targeted RN versions.

#if RCT_NEW_ARCH_ENABLED
#if canImport(React_Codegen)
// RN 0.78: codegen-generated protocol
extension RNUsercentricsModule: NativeUsercentricsSpec {
    func getTurboModule(jsInvoker: RCTJSInvoker) -> Any {
        return self
    }
}
#elseif canImport(RNUsercentricsModuleSpec)
// RN ≤ 0.77
extension RNUsercentricsModule: NativeUsercentricsSpec {
    func getTurboModule(jsInvoker: RCTJSInvoker) -> Any {
        return self
    }
}
#endif
#else
extension RNUsercentricsModule: RCTBridgeModule {}
#endif

}
#endif
#else
extension RNUsercentricsModule: RCTBridgeModule {

}
extension RNUsercentricsModule: RCTBridgeModule {}
#endif
18 changes: 6 additions & 12 deletions react-native-usercentrics.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ Pod::Spec.new do |s|
s.homepage = package['homepage']
s.platform = :ios, "11.0"

# Use apenas o path local para desenvolvimento
s.source = { :path => '.' }

s.source_files = 'ios/**/*.{h,m,mm,swift}'
Expand All @@ -21,9 +20,12 @@ Pod::Spec.new do |s|
s.dependency 'React-NativeModulesApple'
s.dependency 'UsercentricsUI', "#{package['iosPackageVersion']}"

# Base C++ configuration
# Note: RCT_NEW_ARCH_ENABLED is inherited from parent project build settings
# This ensures compatibility with Expo's prebuild process
# Required for TurboModules RN 0.78+: injects codegen dependencies (ReactCodegen, etc.)
if defined?(install_modules_dependencies)
install_modules_dependencies(s)
end
Comment on lines +23 to +26
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] The podspec now calls install_modules_dependencies(s) when defined to inject codegen dependencies, but it no longer provides a fallback header_search_paths addition for environments where install_modules_dependencies isn't defined (older RN versions or custom prebuild flows). This can lead to missing React-Codegen / React-Fabric headers and broken iOS builds. Actionable fix: add a fallback branch that appends the React-Fabric/React-Codegen header paths (the previously removed entries) when install_modules_dependencies is not defined, or explicitly check supported RN versions and document that install_modules_dependencies must exist in the consuming project.

  # Required for TurboModules RN 0.78+: injects codegen dependencies (ReactCodegen, etc.)
  if defined?(install_modules_dependencies)
    install_modules_dependencies(s)
  else
    # Fallback for projects without install_modules_dependencies (older RN / custom setups)
    header_search_paths += [
      '$(PODS_ROOT)/Headers/Public/React-Fabric',
      '$(PODS_ROOT)/Headers/Public/React-Codegen',
      '$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers',
      '$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.framework/Headers'
    ]
  end

  # C++ configuration (compatible with Expo prebuild and New Architecture)
  base_cpp_flags = {
    'CLANG_CXX_LANGUAGE_STANDARD' => 'c++20',
    'CLANG_CXX_LIBRARY' => 'libc++',
    'OTHER_CPLUSPLUSFLAGS' => '-std=c++20 -stdlib=libc++ $(inherited)',
    'CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER' => 'NO',
    'CLANG_WARN_DOCUMENTATION_COMMENTS' => 'NO',
    'GCC_WARN_INHIBIT_ALL_WARNINGS' => 'YES',
    'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES',
    'DEFINES_MODULE' => 'YES',
    'USE_HEADERMAP' => 'YES',
    'ALWAYS_SEARCH_USER_PATHS' => 'NO'
  }

  base_cpp_flags['HEADER_SEARCH_PATHS'] = header_search_paths.map { |path| "\"#{path}\"" }.join(' ')


# C++ configuration (compatible with Expo prebuild and New Architecture)
base_cpp_flags = {
'CLANG_CXX_LANGUAGE_STANDARD' => 'c++20',
'CLANG_CXX_LIBRARY' => 'libc++',
Expand All @@ -50,14 +52,6 @@ Pod::Spec.new do |s|
'$(PODS_ROOT)/Headers/Public/ReactCommon'
]

# Add new architecture paths if available (will be resolved at build time)
header_search_paths += [
'$(PODS_ROOT)/Headers/Public/React-Fabric',
'$(PODS_ROOT)/Headers/Public/React-Codegen',
'$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers',
'$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.framework/Headers'
]

base_cpp_flags['HEADER_SEARCH_PATHS'] = header_search_paths.map { |path| "\"#{path}\"" }.join(' ')

# Preprocessor definitions - inherit RCT_NEW_ARCH_ENABLED from parent project
Expand Down