brick-module 0.1.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.
@@ -0,0 +1,56 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+ folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
5
+
6
+ Pod::Spec.new do |s|
7
+ s.name = "BrickModule"
8
+ s.version = package["version"]
9
+ s.summary = package["description"]
10
+ s.homepage = package["homepage"]
11
+ s.license = package["license"]
12
+ s.authors = package["author"]
13
+
14
+ s.platforms = { :ios => '13.0' }
15
+ s.source = { :git => "https://github.com/toss/brick.git", :tag => "#{s.version}" }
16
+ s.source_files = "ios/**/*.{h,m,mm,swift}"
17
+ s.public_header_files = "ios/BrickModule/Public/*.h"
18
+ s.private_header_files = "ios/BrickModule/Internal/*.h"
19
+
20
+ # Swift 설정
21
+ s.swift_version = "5.0"
22
+ s.requires_arc = true
23
+
24
+ # Base configuration
25
+ base_config = {
26
+ "DEFINES_MODULE" => "YES",
27
+ "SWIFT_VERSION" => "5.0",
28
+ "OTHER_SWIFT_FLAGS" => "-enable-experimental-feature AccessLevelOnImport"
29
+ }
30
+
31
+ # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
32
+ # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
33
+ if respond_to?(:install_modules_dependencies, true)
34
+ install_modules_dependencies(s)
35
+ s.pod_target_xcconfig = base_config
36
+ else
37
+ s.dependency "React-Core"
38
+
39
+ # Don't install the dependencies when we run `pod install` in the old architecture.
40
+ if ENV["RCT_NEW_ARCH_ENABLED"] == "1" then
41
+ s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
42
+ s.pod_target_xcconfig = base_config.merge({
43
+ "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
44
+ "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
45
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
46
+ })
47
+ s.dependency "React-Codegen"
48
+ s.dependency "RCT-Folly"
49
+ s.dependency "RCTRequired"
50
+ s.dependency "RCTTypeSafety"
51
+ s.dependency "ReactCommon/turbomodule/core"
52
+ else
53
+ s.pod_target_xcconfig = base_config
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,280 @@
1
+ /*
2
+ * Brick Modules Gradle Configuration
3
+ * This file provides automatic configuration for brick modules in React Native projects.
4
+ *
5
+ * Usage: Add to settings.gradle only:
6
+ * apply from: file("../node_modules/brick-module/android/brick_modules.gradle")
7
+ * applyBrickModules(settings)
8
+ */
9
+
10
+ import groovy.json.JsonSlurper
11
+
12
+ // =============================================================================
13
+ // Utility Functions - Store as ext properties for global access
14
+ // =============================================================================
15
+
16
+ ext.brickLog = { message ->
17
+ println("🧱 BrickModules: $message")
18
+ }
19
+
20
+ ext.resolveModule = { workingDir, moduleName ->
21
+ try {
22
+ def proc = ['node', '-p', "require.resolve('${moduleName}/package.json')"].execute(null, workingDir)
23
+ proc.waitFor()
24
+
25
+ if (proc.exitValue() == 0) {
26
+ def packageJsonPath = proc.text.trim()
27
+ if (packageJsonPath && !packageJsonPath.isEmpty()) {
28
+ return new File(packageJsonPath).parentFile
29
+ }
30
+ }
31
+ } catch (Exception e) {
32
+ // Silent fail - module not found
33
+ }
34
+ return null
35
+ }
36
+
37
+ ext.readPackageJson = { File packageJsonFile ->
38
+ if (!packageJsonFile.exists()) return null
39
+ try {
40
+ return new JsonSlurper().parse(packageJsonFile)
41
+ } catch (Exception e) {
42
+ return null
43
+ }
44
+ }
45
+
46
+ ext.getAllDependencies = { packageJson ->
47
+ def deps = []
48
+ deps.addAll(packageJson.dependencies?.keySet() ?: [])
49
+ deps.addAll(packageJson.devDependencies?.keySet() ?: [])
50
+ return deps
51
+ }
52
+
53
+ ext.isBrickModule = { packageJson ->
54
+ return packageJson?.brickModule != null
55
+ }
56
+
57
+ ext.runBrickCodegen = { workingDir ->
58
+ def brickModuleDir = resolveModule(workingDir, "brick-module")
59
+ if (brickModuleDir == null) {
60
+ brickLog("brick-module not found, skipping code generation")
61
+ return false
62
+ }
63
+
64
+ def codegenPath = new File(brickModuleDir, "bin/brick-codegen.js")
65
+ if (!codegenPath.exists()) {
66
+ brickLog("brick-codegen not found at ${codegenPath}")
67
+ return false
68
+ }
69
+
70
+ try {
71
+ def proc = ['node', codegenPath.absolutePath, '--platform', 'android'].execute(null, workingDir)
72
+ proc.waitFor()
73
+ return proc.exitValue() == 0
74
+ } catch (Exception e) {
75
+ brickLog("Failed to run brick-codegen: ${e.message}")
76
+ return false
77
+ }
78
+ }
79
+
80
+ // =============================================================================
81
+ // Main Configuration
82
+ // =============================================================================
83
+
84
+ ext.applyBrickModules = { settings ->
85
+ def projectRoot = settings.rootDir.parentFile
86
+ def foundModules = []
87
+ def brickModulesData = [:]
88
+
89
+ // Read app's package.json
90
+ def appPackageJson = readPackageJson(new File(projectRoot, "package.json"))
91
+ if (appPackageJson == null) {
92
+ throw new GradleException("Could not find or parse package.json at ${projectRoot}")
93
+ }
94
+
95
+ // Store app package.json for later use
96
+ settings.ext.appPackageJson = appPackageJson
97
+
98
+ // Get all dependencies
99
+ def allDeps = getAllDependencies(appPackageJson)
100
+
101
+ // Always include brick-module if it exists
102
+ def brickModuleDir = resolveModule(projectRoot, "brick-module")
103
+ if (brickModuleDir != null) {
104
+ def androidDir = new File(brickModuleDir, "android")
105
+ if (androidDir.exists()) {
106
+ settings.include(":brick-module")
107
+ settings.project(":brick-module").projectDir = androidDir
108
+ foundModules.add("brick-module")
109
+ }
110
+ }
111
+
112
+ // Scan and include other brick modules
113
+ allDeps.each { depName ->
114
+ if (depName == "brick-module") return // Already handled
115
+
116
+ def moduleDir = resolveModule(projectRoot, depName)
117
+ if (moduleDir == null) return
118
+
119
+ def packageJson = readPackageJson(new File(moduleDir, "package.json"))
120
+ if (!isBrickModule(packageJson)) return
121
+
122
+ def androidDir = new File(moduleDir, "android")
123
+ if (androidDir.exists()) {
124
+ settings.include(":${depName}")
125
+ settings.project(":${depName}").projectDir = androidDir
126
+ foundModules.add(depName)
127
+
128
+ // Store module data for project configuration
129
+ if (packageJson.brickModule.android?.package) {
130
+ brickModulesData[depName] = [
131
+ moduleName: packageJson.brickModule.android.moduleName ?: depName,
132
+ packageName: packageJson.brickModule.android.package
133
+ ]
134
+ }
135
+ }
136
+ }
137
+
138
+ // Check if codegen is needed
139
+ def brickDir = new File(settings.rootDir, ".brick")
140
+ def needsCodegen = !brickDir.exists() || !new File(brickDir, "src/main/kotlin/BrickModule.kt").exists()
141
+
142
+ if (needsCodegen) {
143
+ runBrickCodegen(projectRoot)
144
+ }
145
+
146
+ // Include generated module
147
+ if (brickDir.exists()) {
148
+ settings.include(":brick-generated")
149
+ settings.project(":brick-generated").projectDir = brickDir
150
+ }
151
+
152
+ if (!foundModules.isEmpty()) {
153
+ brickLog("Found modules: ${foundModules.join(', ')}")
154
+ }
155
+
156
+ // Configure app project after all projects are loaded
157
+ settings.gradle.projectsLoaded {
158
+ // Transfer data to root project
159
+ gradle.rootProject.ext.brickModulesData = brickModulesData
160
+ gradle.rootProject.ext.brickModulesList = foundModules
161
+ gradle.rootProject.ext.brickProjectRoot = projectRoot
162
+ configureAppProject(gradle)
163
+ }
164
+ }
165
+
166
+ // Configure the app project
167
+ def configureAppProject(gradle) {
168
+ gradle.rootProject.subprojects { project ->
169
+ if (project.name == 'app') {
170
+ project.afterEvaluate {
171
+ configureBrickModules(project)
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ // Configure brick modules for the app project
178
+ def configureBrickModules(project) {
179
+ def rootProject = project.rootProject
180
+ def brickModulesData = rootProject.ext.brickModulesData
181
+ def projectRoot = project.rootDir.parentFile
182
+
183
+ // Add source directory for generated code
184
+ project.android.sourceSets.main.java.srcDir "${project.buildDir}/generated/source/brick-provider"
185
+
186
+ // Create provider generation task
187
+ project.tasks.create('generateBrickModuleProvider') {
188
+ description = 'Generates BrickModuleProvider class for automatic module registration'
189
+ group = 'brick-module'
190
+
191
+ doLast {
192
+ generateProvider(project, brickModulesData)
193
+ }
194
+ }
195
+
196
+ // Hook into build process
197
+ project.preBuild.dependsOn('generateBrickModuleProvider')
198
+ project.preBuild.doFirst {
199
+ def workingDir = projectRoot
200
+
201
+ // Run codegen inline
202
+ try {
203
+ def proc = ['node', '-p', "require.resolve('brick-module/package.json')"].execute(null, workingDir)
204
+ proc.waitFor()
205
+
206
+ if (proc.exitValue() == 0) {
207
+ def packageJsonPath = proc.text.trim()
208
+ if (packageJsonPath && !packageJsonPath.isEmpty()) {
209
+ def brickModuleDir = new File(packageJsonPath).parentFile
210
+ def codegenPath = new File(brickModuleDir, "bin/brick-codegen.js")
211
+
212
+ if (codegenPath.exists()) {
213
+ def codegenProc = ['node', codegenPath.absolutePath, '--platform', 'android'].execute(null, workingDir)
214
+ codegenProc.waitFor()
215
+ }
216
+ }
217
+ }
218
+ } catch (Exception e) {
219
+ println("🧱 BrickModules: Failed to run brick-codegen: ${e.message}")
220
+ }
221
+ }
222
+
223
+ // Add dependencies
224
+ project.dependencies {
225
+ // Add brick module dependencies
226
+ rootProject.subprojects.each { subproject ->
227
+ if (subproject.name.startsWith('brick-') || brickModulesData.containsKey(subproject.name)) {
228
+ add('implementation', subproject)
229
+ }
230
+ }
231
+
232
+ // Add required Kotlin dependencies
233
+ add('implementation', "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
234
+ add('implementation', "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
235
+ add('implementation', "com.google.code.gson:gson:2.8.9")
236
+ }
237
+ }
238
+
239
+ // Generate BrickModuleProvider.kt
240
+ def generateProvider(project, brickModulesData) {
241
+ def modules = brickModulesData.collect { name, data ->
242
+ [
243
+ name: data.moduleName,
244
+ className: data.moduleName + "Module",
245
+ packageName: data.packageName
246
+ ]
247
+ }
248
+
249
+ def outputDir = project.file("${project.buildDir}/generated/source/brick-provider/com/brickmodule")
250
+ outputDir.mkdirs()
251
+
252
+ def imports = modules.collect { "import ${it.packageName}.${it.className}" }.join("\n")
253
+ def moduleInstances = modules.collect { " ${it.name}Module()" }.join(",\n")
254
+ def moduleNames = modules.collect { " \"${it.name}\"" }.join(",\n")
255
+
256
+ new File(outputDir, "BrickModuleProvider.kt").text = """// Auto-generated by brick_modules.gradle
257
+ package com.brickmodule
258
+
259
+ import com.brickmodule.BrickModuleRegistry
260
+ ${imports}
261
+
262
+ object BrickModuleProvider {
263
+ fun registerAll() {
264
+ val modules = listOf<Any>(
265
+ ${moduleInstances}
266
+ )
267
+
268
+ if (modules.isNotEmpty()) {
269
+ BrickModuleRegistry.register(modules)
270
+ println("🧱 BrickModuleProvider: Registered \${modules.size} modules")
271
+ }
272
+ }
273
+
274
+ fun getAvailableModules(): List<String> = listOf(
275
+ ${moduleNames}
276
+ )
277
+ }
278
+ """
279
+ }
280
+
@@ -0,0 +1,14 @@
1
+ # Dummy CMakeLists.txt for React Native autolinking
2
+ # This file is required by React Native's autolinking system
3
+ # The actual TurboModule implementation is handled by brick-codegen in user projects
4
+ cmake_minimum_required(VERSION 3.13)
5
+ set(CMAKE_VERBOSE_MAKEFILE on)
6
+
7
+ # Create a dummy source file
8
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp "// Dummy file for BrickModuleSpec\n")
9
+
10
+ # Create an empty static library to satisfy React Native's build system
11
+ add_library(react_codegen_BrickModuleSpec STATIC ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp)
12
+
13
+ # Set necessary properties
14
+ target_include_directories(react_codegen_BrickModuleSpec PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
@@ -0,0 +1,144 @@
1
+ buildscript {
2
+ // Buildscript is evaluated before everything else so we can't use getExtOrDefault
3
+ def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["HotUpdater_kotlinVersion"]
4
+
5
+ repositories {
6
+ google()
7
+ mavenCentral()
8
+ }
9
+
10
+ dependencies {
11
+ classpath "com.android.tools.build:gradle:7.2.1"
12
+ // noinspection DifferentKotlinGradleVersion
13
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14
+
15
+ }
16
+ }
17
+
18
+ def reactNativeArchitectures() {
19
+ def value = rootProject.getProperties().get("reactNativeArchitectures")
20
+ return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
21
+ }
22
+
23
+ def isNewArchitectureEnabled() {
24
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
25
+ }
26
+
27
+ apply plugin: "com.android.library"
28
+ apply plugin: "kotlin-android"
29
+ apply from: "$projectDir/react-native-helpers.gradle"
30
+
31
+ if (isNewArchitectureEnabled()) {
32
+ apply plugin: "com.facebook.react"
33
+ }
34
+
35
+ def getExtOrDefault(name) {
36
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["BrickModule_" + name]
37
+ }
38
+
39
+ def getExtOrIntegerDefault(name) {
40
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["BrickModule_" + name]).toInteger()
41
+ }
42
+
43
+ def supportsNamespace() {
44
+ def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
45
+ def major = parsed[0].toInteger()
46
+ def minor = parsed[1].toInteger()
47
+
48
+ // Namespace support was added in 7.3.0
49
+ return (major == 7 && minor >= 3) || major >= 8
50
+ }
51
+
52
+ android {
53
+ if (supportsNamespace()) {
54
+ namespace "com.brickmodule"
55
+
56
+ sourceSets {
57
+ main {
58
+ manifest.srcFile "src/main/AndroidManifest.xml"
59
+ }
60
+ }
61
+ }
62
+
63
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
64
+
65
+ defaultConfig {
66
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
67
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
68
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
69
+ consumerProguardFiles 'proguard-rules.pro'
70
+ buildConfigField "long", "BUILD_TIMESTAMP", "${System.currentTimeMillis()}L"
71
+ }
72
+
73
+ buildFeatures {
74
+ buildConfig true
75
+ }
76
+
77
+ buildTypes {
78
+ release {
79
+ minifyEnabled false
80
+ }
81
+ }
82
+
83
+ lintOptions {
84
+ disable "GradleCompatible"
85
+ }
86
+
87
+ compileOptions {
88
+ sourceCompatibility JavaVersion.VERSION_1_8
89
+ targetCompatibility JavaVersion.VERSION_1_8
90
+ }
91
+ }
92
+
93
+ repositories {
94
+ mavenCentral()
95
+ google()
96
+ }
97
+
98
+ def kotlin_version = getExtOrDefault("kotlinVersion")
99
+
100
+ dependencies {
101
+ // For < 0.71, this will be from the local maven repo
102
+ // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
103
+ //noinspection GradleDynamicVersion
104
+ if (project.ext.shouldConsumeReactNativeFromMavenCentral()) {
105
+ // noinspection GradleDynamicVersion
106
+ implementation 'com.facebook.react:react-android:+'
107
+ } else {
108
+ // noinspection GradleDynamicVersion
109
+ implementation 'com.facebook.react:react-native:+'
110
+ }
111
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
112
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
113
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
114
+ }
115
+
116
+ // Custom clean task that preserves CMakeLists.txt
117
+ task cleanButPreserveCMakeLists {
118
+ doFirst {
119
+ def cmakeFile = file("$buildDir/generated/source/codegen/jni/CMakeLists.txt")
120
+ def cmakeContent = ""
121
+
122
+ // Save CMakeLists.txt content if it exists
123
+ if (cmakeFile.exists()) {
124
+ cmakeContent = cmakeFile.text
125
+ }
126
+
127
+ // Store in project property for restoration
128
+ project.ext.savedCMakeContent = cmakeContent
129
+ }
130
+ }
131
+
132
+ // Override the clean task to preserve CMakeLists.txt
133
+ clean {
134
+ dependsOn cleanButPreserveCMakeLists
135
+
136
+ doLast {
137
+ // Restore CMakeLists.txt after clean
138
+ if (project.hasProperty('savedCMakeContent') && project.savedCMakeContent) {
139
+ def cmakeFile = file("$buildDir/generated/source/codegen/jni/CMakeLists.txt")
140
+ cmakeFile.parentFile.mkdirs()
141
+ cmakeFile.text = project.savedCMakeContent
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,5 @@
1
+ BrickModule_kotlinVersion=2.0.21
2
+ BrickModule_minSdkVersion=24
3
+ BrickModule_targetSdkVersion=34
4
+ BrickModule_compileSdkVersion=35
5
+ BrickModule_ndkVersion=27.1.12297006
@@ -0,0 +1,42 @@
1
+ def safeAppExtGet(prop, fallback) {
2
+ def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') }
3
+ appProject?.ext?.has(prop) ? appProject.ext.get(prop) : fallback
4
+ }
5
+
6
+ // Let's detect react-native's directory, it will be used to determine RN's version
7
+ // https://github.com/software-mansion/react-native-reanimated/blob/36c291a15880c78a94dd125c51484630546ceb7c/packages/react-native-reanimated/android/build.gradle#L73
8
+ def resolveReactNativeDirectory() {
9
+ def reactNativeLocation = safeAppExtGet("REACT_NATIVE_NODE_MODULES_DIR", null)
10
+ if (reactNativeLocation != null) {
11
+ return file(reactNativeLocation)
12
+ }
13
+
14
+ // Fallback to node resolver for custom directory structures like monorepos.
15
+ def reactNativePackage = file(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim())
16
+ if (reactNativePackage.exists()) {
17
+ return reactNativePackage.parentFile
18
+ }
19
+
20
+ throw new GradleException(
21
+ "${project.name}: unable to resolve react-native location in " +
22
+ "node_modules. You should project extension property (in app/build.gradle) " +
23
+ "`REACT_NATIVE_NODE_MODULES_DIR` with path to react-native."
24
+ )
25
+ }
26
+
27
+ // https://github.com/software-mansion/react-native-reanimated/blob/cda4627c3337c33674f05f755b7485165c6caca9/android/build.gradle#L199#L205
28
+ def reactNativeRootDir = resolveReactNativeDirectory()
29
+
30
+ def reactProperties = new Properties()
31
+ file("$reactNativeRootDir/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }
32
+
33
+ def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME")
34
+ def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger()
35
+
36
+ project.ext.resolveReactNativeDirectory = { ->
37
+ return resolveReactNativeDirectory()
38
+ }
39
+
40
+ project.ext.shouldConsumeReactNativeFromMavenCentral = { ->
41
+ return REACT_NATIVE_MINOR_VERSION >= 71
42
+ }
@@ -0,0 +1,3 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.brickmodule">
3
+ </manifest>
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,23 @@
1
+ package com.brickmodule
2
+
3
+ /**
4
+ * Minimal interface that all Brick modules must implement
5
+ * Contains only essential properties for module identification
6
+ */
7
+ interface BrickModuleBase {
8
+ /**
9
+ * The name of the module (required for registration)
10
+ */
11
+ val moduleName: String
12
+ }
13
+
14
+ /**
15
+ * Error types for Brick modules
16
+ */
17
+ open class BrickModuleError(message: String, val errorCode: String) : Exception(message) {
18
+ class TypeMismatch(message: String) : BrickModuleError("Type mismatch: $message", "TYPE_ERROR")
19
+ class ExecutionError(message: String) : BrickModuleError("Execution error: $message", "EXECUTION_ERROR")
20
+ class InvalidDefinition(message: String) : BrickModuleError("Invalid definition: $message", "DEFINITION_ERROR")
21
+ class MethodNotFound(message: String) : BrickModuleError("Method not found: $message", "METHOD_NOT_FOUND")
22
+ class ModuleNotFound(message: String) : BrickModuleError("Module not found: $message", "MODULE_NOT_FOUND")
23
+ }
@@ -0,0 +1,87 @@
1
+ @file:Suppress("DEPRECATION")
2
+
3
+ package com.brickmodule
4
+
5
+ import com.facebook.react.TurboReactPackage
6
+ import com.facebook.react.bridge.NativeModule
7
+ import com.facebook.react.bridge.ReactApplicationContext
8
+ import com.facebook.react.module.model.ReactModuleInfo
9
+ import com.facebook.react.module.model.ReactModuleInfoProvider
10
+ import java.util.HashMap
11
+
12
+ class BrickModulePackage : TurboReactPackage() {
13
+
14
+ init {
15
+ println("🔍 BrickModulePackage initialized")
16
+ }
17
+
18
+ override fun getModule(
19
+ name: String,
20
+ reactContext: ReactApplicationContext,
21
+ ): NativeModule? {
22
+ println("🔍 BrickModulePackage.getModule called with name: $name")
23
+ return if (name == "BrickModule") {
24
+ // Try to find the generated BrickModule class
25
+ try {
26
+ // Try with app's class loader first
27
+ val classLoader = reactContext.applicationContext.classLoader
28
+ val generatedClass =
29
+ Class.forName("com.brickmodule.codegen.BrickModule", true, classLoader)
30
+ val constructor = generatedClass.getConstructor(ReactApplicationContext::class.java)
31
+ val instance = constructor.newInstance(reactContext) as NativeModule
32
+ println("✅ BrickModule successfully created: ${instance.javaClass.name}")
33
+ println("BrickModule ${instance.javaClass.methods.map { it.name }}")
34
+ instance
35
+ } catch (e: ClassNotFoundException) {
36
+ // Try with current thread class loader as fallback
37
+ try {
38
+ val currentClassLoader = Thread.currentThread().contextClassLoader
39
+ val generatedClass =
40
+ Class.forName("com.brickmodule.BrickModule", true, currentClassLoader)
41
+ val constructor =
42
+ generatedClass.getConstructor(ReactApplicationContext::class.java)
43
+ val instance = constructor.newInstance(reactContext) as NativeModule
44
+ println(
45
+ "✅ BrickModule successfully created with thread classloader: ${instance.javaClass.name}"
46
+ )
47
+ instance
48
+ } catch (e2: Exception) {
49
+ e.printStackTrace()
50
+ e2.printStackTrace()
51
+ throw RuntimeException(
52
+ "BrickModule not found in any classloader. Please run 'brick-codegen' to generate the bridge code. " +
53
+ "The generated BrickModule.kt should be in your app's source directory. " +
54
+ "Original error: ${e.message}, Fallback error: ${e2.message}"
55
+ )
56
+ }
57
+ } catch (e: Exception) {
58
+ e.printStackTrace()
59
+ throw RuntimeException("Failed to create BrickModule instance: ${e.message}", e)
60
+ }
61
+ } else {
62
+ null
63
+ }
64
+ }
65
+
66
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider = ReactModuleInfoProvider {
67
+ println("🔍 BrickModulePackage.getReactModuleInfoProvider called")
68
+ val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
69
+ // Force TurboModule to true since we're using NativeBrickModuleSpec
70
+ val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
71
+ moduleInfos["BrickModule"] =
72
+ ReactModuleInfo(
73
+ "BrickModule",
74
+ "com.brickmodule.codegen.BrickModule",
75
+ false, // canOverrideExistingModule
76
+ false, // needsEagerInit
77
+ true, // hasConstants
78
+ false, // isCxxModule
79
+ isTurboModule, // isTurboModule
80
+ )
81
+ moduleInfos
82
+ }
83
+
84
+ companion object {
85
+ const val NAME = "BrickModulePackage"
86
+ }
87
+ }