brick-module 0.1.5 → 0.1.7
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.
- package/BrickModule.podspec +6 -8
- package/android/brick_modules.gradle +126 -4
- package/android/build.gradle +0 -1
- package/android/src/main/java/com/brickmodule/BrickModulePackage.kt +2 -3
- package/dist/BrickModule.js +5 -1
- package/dist/index.js +3 -3
- package/ios/BrickModule/{Internal/BrickCoreModule.swift → BrickCoreModule.swift} +30 -9
- package/ios/BrickModule/BrickModuleRegistrable.swift +26 -0
- package/ios/BrickModule/BrickModuleRegistrableViewControllerType.swift +5 -0
- package/ios/BrickModule/{Internal/BrickModuleRegistry.swift → BrickModuleRegistry.swift} +31 -40
- package/package.json +15 -4
- package/podfile_helper.rb +122 -8
- package/src/index.ts +1 -1
- package/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -14
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +0 -7
- package/android/gradlew +0 -252
- package/android/gradlew.bat +0 -94
- package/ios/BrickModule/Public/BrickModule-Swift.h +0 -341
package/BrickModule.podspec
CHANGED
|
@@ -25,6 +25,9 @@ Pod::Spec.new do |s|
|
|
|
25
25
|
base_config = {
|
|
26
26
|
"DEFINES_MODULE" => "YES",
|
|
27
27
|
"SWIFT_VERSION" => "5.0",
|
|
28
|
+
"SWIFT_COMPILATION_MODE" => "wholemodule",
|
|
29
|
+
"SWIFT_INSTALL_OBJC_HEADER" => "YES",
|
|
30
|
+
"SWIFT_OBJC_INTERFACE_HEADER_NAME" => "BrickModule-Swift.h",
|
|
28
31
|
"OTHER_SWIFT_FLAGS" => "-enable-experimental-feature AccessLevelOnImport"
|
|
29
32
|
}
|
|
30
33
|
|
|
@@ -36,22 +39,17 @@ Pod::Spec.new do |s|
|
|
|
36
39
|
else
|
|
37
40
|
s.dependency "React-Core"
|
|
38
41
|
|
|
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
42
|
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
42
43
|
s.pod_target_xcconfig = base_config.merge({
|
|
43
44
|
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
44
45
|
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
45
46
|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
46
47
|
})
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
s.dependency "React-Codegen"
|
|
49
50
|
s.dependency "RCT-Folly"
|
|
50
51
|
s.dependency "RCTRequired"
|
|
51
52
|
s.dependency "RCTTypeSafety"
|
|
52
53
|
s.dependency "ReactCommon/turbomodule/core"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -43,6 +43,89 @@ ext.readPackageJson = { File packageJsonFile ->
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
ext.findBrickJson = { startDir ->
|
|
47
|
+
// Walk up the directory tree looking for brick.json
|
|
48
|
+
if (!startDir) {
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
// startDir can be either a File or String, handle both
|
|
54
|
+
def current = startDir instanceof File ? startDir.canonicalFile : new File(startDir).canonicalFile
|
|
55
|
+
def root = new File('/').canonicalFile
|
|
56
|
+
|
|
57
|
+
while (current != root && current != null) {
|
|
58
|
+
def brickJsonFile = new File(current, 'brick.json')
|
|
59
|
+
if (brickJsonFile.exists()) {
|
|
60
|
+
return brickJsonFile
|
|
61
|
+
}
|
|
62
|
+
def parent = current.parentFile
|
|
63
|
+
if (parent == current || parent == null) break // Reached filesystem root
|
|
64
|
+
current = parent
|
|
65
|
+
}
|
|
66
|
+
} catch (Exception e) {
|
|
67
|
+
// Failed to process directory, return null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return null
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
ext.resolveProjectRoot = { projectRootPath, configDir ->
|
|
74
|
+
// Handle both absolute and relative paths
|
|
75
|
+
if (!projectRootPath || !configDir) {
|
|
76
|
+
return null
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
def projectRootFile = new File(projectRootPath)
|
|
81
|
+
if (projectRootFile.isAbsolute()) {
|
|
82
|
+
return projectRootFile.exists() ? projectRootFile : null
|
|
83
|
+
} else {
|
|
84
|
+
// Relative to brick.json location
|
|
85
|
+
def resolvedFile = new File(configDir, projectRootPath).canonicalFile
|
|
86
|
+
return resolvedFile.exists() ? resolvedFile : null
|
|
87
|
+
}
|
|
88
|
+
} catch (Exception e) {
|
|
89
|
+
return null
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
ext.getBrickAndroidPath = { searchRoot ->
|
|
94
|
+
// Walk up directory tree to find brick.json
|
|
95
|
+
def brickConfigFile = findBrickJson(searchRoot)
|
|
96
|
+
|
|
97
|
+
if (brickConfigFile && brickConfigFile.exists()) {
|
|
98
|
+
try {
|
|
99
|
+
def config = new JsonSlurper().parse(brickConfigFile)
|
|
100
|
+
|
|
101
|
+
// Get the effective project root
|
|
102
|
+
def effectiveRoot = brickConfigFile.parentFile
|
|
103
|
+
if (config.projectRoot) {
|
|
104
|
+
def resolvedRoot = resolveProjectRoot(config.projectRoot, brickConfigFile.parentFile)
|
|
105
|
+
if (resolvedRoot) {
|
|
106
|
+
effectiveRoot = resolvedRoot
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
def androidPath = config?.output?.android
|
|
111
|
+
if (androidPath && !androidPath.isEmpty()) {
|
|
112
|
+
// Handle absolute paths (though not recommended)
|
|
113
|
+
if (new File(androidPath).isAbsolute()) {
|
|
114
|
+
println("[Brick] Warning: Using absolute path for Android output is not recommended: ${androidPath}")
|
|
115
|
+
return androidPath
|
|
116
|
+
}
|
|
117
|
+
// Otherwise, treat as relative to effective project root
|
|
118
|
+
return new File(effectiveRoot, androidPath).canonicalPath
|
|
119
|
+
}
|
|
120
|
+
} catch (Exception e) {
|
|
121
|
+
println("[Brick] Warning: Failed to parse brick.json: ${e.message}")
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Default: .brick directory in the Android project root
|
|
126
|
+
return new File(searchRoot, '.brick').canonicalPath
|
|
127
|
+
}
|
|
128
|
+
|
|
46
129
|
ext.getAllDependencies = { packageJson ->
|
|
47
130
|
def deps = []
|
|
48
131
|
deps.addAll(packageJson.dependencies?.keySet() ?: [])
|
|
@@ -54,6 +137,44 @@ ext.isBrickModule = { packageJson ->
|
|
|
54
137
|
return packageJson?.brickModule != null
|
|
55
138
|
}
|
|
56
139
|
|
|
140
|
+
ext.findProjectRoot = { androidDir ->
|
|
141
|
+
// 1. Walk up directory tree to find brick.json
|
|
142
|
+
def brickConfigFile = findBrickJson(androidDir)
|
|
143
|
+
if (brickConfigFile) {
|
|
144
|
+
brickLog("Found brick.json at: ${brickConfigFile.canonicalPath}")
|
|
145
|
+
try {
|
|
146
|
+
def config = new JsonSlurper().parse(brickConfigFile)
|
|
147
|
+
if (config.projectRoot) {
|
|
148
|
+
def projectRoot = resolveProjectRoot(config.projectRoot, brickConfigFile.parentFile)
|
|
149
|
+
if (projectRoot) {
|
|
150
|
+
brickLog("Using projectRoot from brick.json: ${projectRoot.canonicalPath}")
|
|
151
|
+
return projectRoot
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// If brick.json exists but has no projectRoot, use its directory as project root
|
|
155
|
+
return brickConfigFile.parentFile
|
|
156
|
+
} catch (Exception e) {
|
|
157
|
+
println("[Brick] Warning: Failed to parse brick.json: ${e.message}")
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// 2. Walk up to find package.json with node_modules
|
|
162
|
+
def current = androidDir
|
|
163
|
+
while (current != null && current != new File('/')) {
|
|
164
|
+
if (new File(current, 'package.json').exists() && new File(current, 'node_modules').exists()) {
|
|
165
|
+
brickLog("Found project root via package.json: ${current.canonicalPath}")
|
|
166
|
+
return current
|
|
167
|
+
}
|
|
168
|
+
def parent = current.parentFile
|
|
169
|
+
if (parent == current) break
|
|
170
|
+
current = parent
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// If no project root found, use default fallback
|
|
174
|
+
brickLog("Warning: Failed to find project root via brick.json or package.json. Using default: ${androidDir.parentFile.canonicalPath}")
|
|
175
|
+
return androidDir.parentFile
|
|
176
|
+
}
|
|
177
|
+
|
|
57
178
|
ext.runBrickCodegen = { workingDir ->
|
|
58
179
|
def brickModuleDir = resolveModule(workingDir, "brick-module")
|
|
59
180
|
if (brickModuleDir == null) {
|
|
@@ -82,7 +203,7 @@ ext.runBrickCodegen = { workingDir ->
|
|
|
82
203
|
// =============================================================================
|
|
83
204
|
|
|
84
205
|
ext.applyBrickModules = { settings ->
|
|
85
|
-
def projectRoot = settings.rootDir
|
|
206
|
+
def projectRoot = findProjectRoot(settings.rootDir)
|
|
86
207
|
def foundModules = []
|
|
87
208
|
def brickModulesData = [:]
|
|
88
209
|
|
|
@@ -144,15 +265,16 @@ ext.applyBrickModules = { settings ->
|
|
|
144
265
|
}
|
|
145
266
|
}
|
|
146
267
|
|
|
147
|
-
// Check if codegen is needed
|
|
148
|
-
def
|
|
268
|
+
// Check if codegen is needed (use configured path)
|
|
269
|
+
def androidBrickPath = getBrickAndroidPath(settings.rootDir)
|
|
270
|
+
def brickDir = new File(androidBrickPath)
|
|
149
271
|
def needsCodegen = !brickDir.exists() || !new File(brickDir, "src/main/kotlin/BrickModule.kt").exists()
|
|
150
272
|
|
|
151
273
|
if (needsCodegen) {
|
|
152
274
|
runBrickCodegen(projectRoot)
|
|
153
275
|
}
|
|
154
276
|
|
|
155
|
-
// Include generated module
|
|
277
|
+
// Include generated module (use configured path)
|
|
156
278
|
if (brickDir.exists()) {
|
|
157
279
|
settings.include(":brick-codegen")
|
|
158
280
|
settings.project(":brick-codegen").projectDir = brickDir
|
package/android/build.gradle
CHANGED
|
@@ -65,7 +65,6 @@ android {
|
|
|
65
65
|
defaultConfig {
|
|
66
66
|
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
67
67
|
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
68
|
-
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
69
68
|
consumerProguardFiles 'proguard-rules.pro'
|
|
70
69
|
buildConfigField "long", "BUILD_TIMESTAMP", "${System.currentTimeMillis()}L"
|
|
71
70
|
}
|
|
@@ -39,8 +39,7 @@ class BrickModulePackage : TurboReactPackage() {
|
|
|
39
39
|
val currentClassLoader = Thread.currentThread().contextClassLoader
|
|
40
40
|
val generatedClass =
|
|
41
41
|
Class.forName("com.brickmodule.BrickModule", true, currentClassLoader)
|
|
42
|
-
val constructor =
|
|
43
|
-
generatedClass.getConstructor(ReactContext::class.java)
|
|
42
|
+
val constructor = generatedClass.getConstructor(ReactContext::class.java)
|
|
44
43
|
val instance = constructor.newInstance(reactContext) as NativeModule
|
|
45
44
|
println(
|
|
46
45
|
"✅ BrickModule successfully created with thread classloader: ${instance.javaClass.name}"
|
|
@@ -68,7 +67,7 @@ class BrickModulePackage : TurboReactPackage() {
|
|
|
68
67
|
println("🔍 BrickModulePackage.getReactModuleInfoProvider called")
|
|
69
68
|
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
70
69
|
// Force TurboModule to true since we're using NativeBrickModuleSpec
|
|
71
|
-
val isTurboModule: Boolean =
|
|
70
|
+
val isTurboModule: Boolean = true
|
|
72
71
|
moduleInfos["BrickModule"] =
|
|
73
72
|
ReactModuleInfo(
|
|
74
73
|
"BrickModule",
|
package/dist/BrickModule.js
CHANGED
|
@@ -82,6 +82,10 @@ const BrickModule = {
|
|
|
82
82
|
getRegisteredModules,
|
|
83
83
|
clearCache
|
|
84
84
|
};
|
|
85
|
+
/**
|
|
86
|
+
* Default export for convenience
|
|
87
|
+
*/
|
|
88
|
+
var BrickModule_default = BrickModule;
|
|
85
89
|
|
|
86
90
|
//#endregion
|
|
87
|
-
export {
|
|
91
|
+
export { BrickModule_default as default };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import BrickModule_default from "./BrickModule.js";
|
|
2
2
|
|
|
3
3
|
//#region src/index.ts
|
|
4
4
|
/**
|
|
5
5
|
* Error types for Brick modules
|
|
6
6
|
*/
|
|
7
7
|
var BrickModuleError = class extends Error {
|
|
8
|
-
constructor(message, code = "
|
|
8
|
+
constructor(message, code = "BRICK_ERROR", moduleName, methodName) {
|
|
9
9
|
super(message);
|
|
10
10
|
this.code = code;
|
|
11
11
|
this.moduleName = moduleName;
|
|
@@ -15,4 +15,4 @@ var BrickModuleError = class extends Error {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
//#endregion
|
|
18
|
-
export { BrickModule, BrickModuleError };
|
|
18
|
+
export { BrickModule_default as BrickModule, BrickModuleError };
|
|
@@ -1,18 +1,39 @@
|
|
|
1
1
|
import Foundation
|
|
2
|
+
import React
|
|
2
3
|
|
|
3
|
-
@objc public protocol BrickModuleRegistableViewControllerType {
|
|
4
|
-
@objc var moduleRegistry: BrickModuleRegistry? { get }
|
|
5
|
-
}
|
|
6
4
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Base class for all Brick modules
|
|
6
|
+
* Provides common functionality including event emission
|
|
9
7
|
*/
|
|
10
|
-
|
|
8
|
+
open class BrickModuleBase: NSObject {
|
|
11
9
|
/// The name of the module (required for registration)
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
public let moduleName: String
|
|
11
|
+
|
|
12
|
+
public weak var eventEmitter: RCTEventEmitter?
|
|
13
|
+
public weak var bridgeProxy: RCTBridgeProxy?
|
|
14
|
+
|
|
15
|
+
/// Initialize with module name
|
|
16
|
+
public init(moduleName: String) {
|
|
17
|
+
self.moduleName = moduleName
|
|
18
|
+
super.init()
|
|
19
|
+
}
|
|
14
20
|
|
|
15
|
-
|
|
21
|
+
/// Sends an event with the given name and data
|
|
22
|
+
/// Automatically prefixes with module name and uses the registry's event emitter
|
|
23
|
+
public func sendEvent(_ eventName: String, data: [String: Any]?) {
|
|
24
|
+
// Format event name with module prefix
|
|
25
|
+
let fullEventName = "\(moduleName)_\(eventName)"
|
|
26
|
+
|
|
27
|
+
// Get the shared event emitter instance and send event
|
|
28
|
+
if let eventEmitter = self.eventEmitter {
|
|
29
|
+
eventEmitter.sendEvent(withName: fullEventName, body: data)
|
|
30
|
+
} else {
|
|
31
|
+
let error = NSError(domain: "BrickModule", code: 500, userInfo: [
|
|
32
|
+
NSLocalizedDescriptionKey: "Event emitter not available, cannot send event: \(fullEventName)"
|
|
33
|
+
])
|
|
34
|
+
print("Error: \(error.localizedDescription)")
|
|
35
|
+
}
|
|
36
|
+
}
|
|
16
37
|
}
|
|
17
38
|
|
|
18
39
|
/**
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//
|
|
2
|
+
// BrickModuleRegistrable.swift
|
|
3
|
+
// BrickModule
|
|
4
|
+
//
|
|
5
|
+
// Protocol for BrickModule registration - Swift-style naming convention
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import UIKit
|
|
9
|
+
import React
|
|
10
|
+
|
|
11
|
+
/// Protocol for BrickModule registration and management
|
|
12
|
+
/// This matches Android's BrickModuleRegistrar interface with Swift naming conventions
|
|
13
|
+
public protocol BrickModuleRegistrable {
|
|
14
|
+
|
|
15
|
+
// MARK: - Module Registry Management
|
|
16
|
+
|
|
17
|
+
/// Module registry - property instead of getter method
|
|
18
|
+
/// This registry manages all registered BrickModules
|
|
19
|
+
var moduleRegistry: BrickModuleRegistry { get }
|
|
20
|
+
|
|
21
|
+
/// Register modules when bridge is ready - using 'on' parameter label
|
|
22
|
+
/// Called after didInitializeBridge to register BrickModules
|
|
23
|
+
func registerModules()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import React
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
/**
|
|
5
6
|
* Central registry for all Brick modules
|
|
6
7
|
* Manages module lifecycle and provides simple module storage
|
|
7
8
|
*/
|
|
8
9
|
@objc public class BrickModuleRegistry: NSObject {
|
|
9
10
|
|
|
10
|
-
private var modules: [String:
|
|
11
|
+
private var modules: [String: BrickModuleBase] = [:]
|
|
11
12
|
private var isRegistered: Bool = false
|
|
12
|
-
|
|
13
|
+
private weak var eventEmitter: RCTEventEmitter?
|
|
14
|
+
private weak var bridgeProxy: RCTBridgeProxy?;
|
|
13
15
|
|
|
14
16
|
public override init() {
|
|
15
17
|
super.init()
|
|
@@ -23,9 +25,8 @@ import React
|
|
|
23
25
|
* This should be called once during app initialization
|
|
24
26
|
*/
|
|
25
27
|
public func register(_ modules: [BrickModuleBase]) {
|
|
26
|
-
|
|
27
|
-
print("
|
|
28
|
-
return
|
|
28
|
+
if isRegistered {
|
|
29
|
+
print("♻️ BrickModuleRegistry: Re-registering modules. Existing modules may be overwritten.")
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
for module in modules {
|
|
@@ -34,10 +35,6 @@ import React
|
|
|
34
35
|
|
|
35
36
|
isRegistered = true
|
|
36
37
|
print("✅ BrickModuleRegistry: Successfully registered \(self.modules.count) modules")
|
|
37
|
-
|
|
38
|
-
if ProcessInfo.processInfo.environment["GRANITE_DEBUG"] == "1" {
|
|
39
|
-
debugPrintRegisteredModules()
|
|
40
|
-
}
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
/**
|
|
@@ -49,7 +46,7 @@ import React
|
|
|
49
46
|
public func registerModules(_ modules: NSArray) {
|
|
50
47
|
let brickModules = modules.compactMap { $0 as? BrickModuleBase }
|
|
51
48
|
register(brickModules)
|
|
52
|
-
|
|
49
|
+
}
|
|
53
50
|
|
|
54
51
|
private func registerSingleModule(_ module: BrickModuleBase) {
|
|
55
52
|
let moduleName = module.moduleName
|
|
@@ -60,14 +57,10 @@ import React
|
|
|
60
57
|
return
|
|
61
58
|
}
|
|
62
59
|
|
|
63
|
-
// Check for module name conflicts
|
|
64
|
-
if modules.keys.contains(moduleName) {
|
|
65
|
-
print("⚠️ BrickModuleRegistry: Module '\(moduleName)' is already registered. Skipping.")
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
|
|
69
60
|
// Register the module
|
|
70
61
|
modules[moduleName] = module
|
|
62
|
+
modules[moduleName]?.eventEmitter = self.eventEmitter;
|
|
63
|
+
modules[moduleName]?.bridgeProxy = self.bridgeProxy;
|
|
71
64
|
print("📦 BrickModuleRegistry: Registered module '\(moduleName)'")
|
|
72
65
|
}
|
|
73
66
|
|
|
@@ -81,6 +74,14 @@ import React
|
|
|
81
74
|
return modules[moduleName]
|
|
82
75
|
}
|
|
83
76
|
|
|
77
|
+
|
|
78
|
+
public func setBridge(_ bridge: Any) {
|
|
79
|
+
self.bridgeProxy = bridge as? RCTBridgeProxy;
|
|
80
|
+
for module in modules {
|
|
81
|
+
module.value.bridgeProxy = self.bridgeProxy;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
84
85
|
/**
|
|
85
86
|
* Returns list of registered module names
|
|
86
87
|
*/
|
|
@@ -92,11 +93,13 @@ import React
|
|
|
92
93
|
|
|
93
94
|
/**
|
|
94
95
|
* Sets the React Native event emitter instance for event emission
|
|
95
|
-
* This should be called during app initialization
|
|
96
|
+
* This should be called during app initialization frBrickModuleom the main BrickModule
|
|
96
97
|
*/
|
|
97
|
-
|
|
98
|
-
self.eventEmitter = eventEmitter
|
|
99
|
-
|
|
98
|
+
public func setEventEmitter(_ eventEmitter: Any) {
|
|
99
|
+
self.eventEmitter = eventEmitter as? RCTEventEmitter
|
|
100
|
+
for module in modules {
|
|
101
|
+
module.value.eventEmitter = self.eventEmitter
|
|
102
|
+
}
|
|
100
103
|
}
|
|
101
104
|
|
|
102
105
|
/**
|
|
@@ -106,36 +109,24 @@ import React
|
|
|
106
109
|
@objc public func getEventEmitter() -> RCTEventEmitter? {
|
|
107
110
|
return eventEmitter
|
|
108
111
|
}
|
|
109
|
-
|
|
110
|
-
// MARK: - Debug & Development
|
|
111
|
-
|
|
112
|
-
private func debugPrintRegisteredModules() {
|
|
113
|
-
print("🔍 BrickModuleRegistry Debug Info:")
|
|
114
|
-
print(" Total Modules: \(modules.count)")
|
|
115
112
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Unregisters all modules and clears their registry references
|
|
115
|
+
*/
|
|
116
|
+
@objc public func unregister() {
|
|
117
|
+
modules.removeAll()
|
|
118
|
+
isRegistered = false
|
|
120
119
|
}
|
|
121
120
|
|
|
122
121
|
/**
|
|
123
122
|
* Clears all registered modules (for testing purposes only)
|
|
124
123
|
*/
|
|
125
124
|
@objc public func clearRegistry() {
|
|
126
|
-
|
|
127
|
-
ProcessInfo.processInfo.environment["GRANITE_ALLOW_CLEAR"] == "1" else {
|
|
128
|
-
print("⚠️ BrickModuleRegistry: clearRegistry() is only allowed in test environment")
|
|
129
|
-
return
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
modules.removeAll()
|
|
133
|
-
isRegistered = false
|
|
134
|
-
|
|
135
|
-
print("🧹 BrickModuleRegistry: Registry cleared")
|
|
125
|
+
unregister()
|
|
136
126
|
}
|
|
137
127
|
}
|
|
138
128
|
|
|
139
129
|
public class ModuleRegistry {
|
|
140
130
|
|
|
141
131
|
}
|
|
132
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brick-module",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Better React Native native module development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,8 +16,19 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"dist/",
|
|
19
|
-
"ios
|
|
20
|
-
"android
|
|
19
|
+
"ios",
|
|
20
|
+
"android",
|
|
21
|
+
"react-native.config.js",
|
|
22
|
+
"!ios/build",
|
|
23
|
+
"!android/build",
|
|
24
|
+
"!android/gradle",
|
|
25
|
+
"!android/gradlew",
|
|
26
|
+
"!android/gradlew.bat",
|
|
27
|
+
"!android/local.properties",
|
|
28
|
+
"!**/__tests__",
|
|
29
|
+
"!**/__fixtures__",
|
|
30
|
+
"!**/__mocks__",
|
|
31
|
+
"!**/.*",
|
|
21
32
|
"src/",
|
|
22
33
|
"bin/",
|
|
23
34
|
"BrickModule.podspec",
|
|
@@ -51,7 +62,7 @@
|
|
|
51
62
|
"brick-codegen": "./bin/brick-codegen.js"
|
|
52
63
|
},
|
|
53
64
|
"dependencies": {
|
|
54
|
-
"brick-codegen": "0.1.
|
|
65
|
+
"brick-codegen": "0.1.7"
|
|
55
66
|
},
|
|
56
67
|
"peerDependencies": {
|
|
57
68
|
"react": ">=18.2.0",
|
package/podfile_helper.rb
CHANGED
|
@@ -6,14 +6,82 @@
|
|
|
6
6
|
require 'json'
|
|
7
7
|
require 'pathname'
|
|
8
8
|
|
|
9
|
+
def find_brick_json(start_dir)
|
|
10
|
+
# Walk up the directory tree looking for brick.json
|
|
11
|
+
current = File.expand_path(start_dir)
|
|
12
|
+
root = File.expand_path('/')
|
|
13
|
+
|
|
14
|
+
while current != root
|
|
15
|
+
brick_json_path = File.join(current, 'brick.json')
|
|
16
|
+
if File.exist?(brick_json_path)
|
|
17
|
+
return brick_json_path
|
|
18
|
+
end
|
|
19
|
+
parent = File.dirname(current)
|
|
20
|
+
break if parent == current # Reached filesystem root
|
|
21
|
+
current = parent
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
return nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def find_project_root
|
|
28
|
+
ios_root = Pod::Config.instance.installation_root
|
|
29
|
+
|
|
30
|
+
# 1. Walk up directory tree to find brick.json
|
|
31
|
+
brick_json_path = find_brick_json(ios_root)
|
|
32
|
+
if brick_json_path
|
|
33
|
+
Pod::UI.puts "[Brick] Found brick.json at: #{brick_json_path}"
|
|
34
|
+
begin
|
|
35
|
+
config = JSON.parse(File.read(brick_json_path))
|
|
36
|
+
if config['projectRoot']
|
|
37
|
+
project_root = resolve_project_root(config['projectRoot'], File.dirname(brick_json_path))
|
|
38
|
+
if project_root
|
|
39
|
+
Pod::UI.puts "[Brick] Using projectRoot from brick.json: #{project_root}"
|
|
40
|
+
return project_root
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
# If brick.json exists but has no projectRoot, use its directory as project root
|
|
44
|
+
return File.dirname(brick_json_path)
|
|
45
|
+
rescue => e
|
|
46
|
+
Pod::UI.warn "[Brick] Failed to parse brick.json: #{e.message}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# 2. Walk up to find package.json with node_modules
|
|
51
|
+
current = ios_root
|
|
52
|
+
while current != '/'
|
|
53
|
+
if File.exist?(File.join(current, 'package.json')) && File.exist?(File.join(current, 'node_modules'))
|
|
54
|
+
Pod::UI.puts "[Brick] Found project root via package.json: #{current}"
|
|
55
|
+
return current
|
|
56
|
+
end
|
|
57
|
+
parent = File.dirname(current)
|
|
58
|
+
break if parent == current
|
|
59
|
+
current = parent
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# If no project root found, use default fallback
|
|
63
|
+
default_root = File.expand_path(File.join(ios_root, '..'))
|
|
64
|
+
Pod::UI.warn "[Brick] Warning: Failed to find project root via brick.json or package.json. Using default: #{default_root}"
|
|
65
|
+
return default_root
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def resolve_project_root(project_root_path, config_dir)
|
|
69
|
+
# Handle both absolute and relative paths
|
|
70
|
+
if Pathname.new(project_root_path).absolute?
|
|
71
|
+
return project_root_path if File.exist?(project_root_path)
|
|
72
|
+
else
|
|
73
|
+
# Relative to brick.json location
|
|
74
|
+
resolved_path = File.expand_path(File.join(config_dir, project_root_path))
|
|
75
|
+
return resolved_path if File.exist?(resolved_path)
|
|
76
|
+
end
|
|
77
|
+
return nil
|
|
78
|
+
end
|
|
79
|
+
|
|
9
80
|
def use_brick_modules!
|
|
10
|
-
brick_root =
|
|
81
|
+
brick_root = find_project_root
|
|
11
82
|
discovered_modules = []
|
|
12
83
|
|
|
13
84
|
begin
|
|
14
|
-
# Discover Brick modules before running codegen
|
|
15
|
-
discovered_modules = discover_brick_modules(brick_root)
|
|
16
|
-
|
|
17
85
|
# Run brick-codegen with real-time output and colors (iOS only)
|
|
18
86
|
exit_status = system("cd #{brick_root} && FORCE_COLOR=1 npx brick-codegen --platform ios")
|
|
19
87
|
|
|
@@ -21,9 +89,18 @@ def use_brick_modules!
|
|
|
21
89
|
# Generate BrickModuleProvider.swift for auto-registration
|
|
22
90
|
generate_brick_module_provider(brick_root, discovered_modules)
|
|
23
91
|
|
|
92
|
+
# Get iOS output path from brick.json if it exists
|
|
93
|
+
ios_brick_path = get_brick_ios_path(brick_root)
|
|
94
|
+
|
|
95
|
+
# Handle relative vs absolute paths
|
|
96
|
+
if Pathname.new(ios_brick_path).absolute?
|
|
97
|
+
brick_codegen_pod_path = ios_brick_path
|
|
98
|
+
else
|
|
99
|
+
brick_codegen_pod_path = File.expand_path(File.join(brick_root, ios_brick_path))
|
|
100
|
+
end
|
|
101
|
+
|
|
24
102
|
# Add generated BrickCodegen pod if it exists
|
|
25
|
-
brick_codegen_podspec_path = "
|
|
26
|
-
brick_codegen_pod_path = "#{brick_root}/ios/.brick"
|
|
103
|
+
brick_codegen_podspec_path = File.join(brick_codegen_pod_path, "BrickCodegen.podspec")
|
|
27
104
|
|
|
28
105
|
if File.exist?(brick_codegen_podspec_path)
|
|
29
106
|
begin
|
|
@@ -98,11 +175,48 @@ def discover_brick_modules(project_root)
|
|
|
98
175
|
modules
|
|
99
176
|
end
|
|
100
177
|
|
|
178
|
+
def get_brick_ios_path(project_root)
|
|
179
|
+
# Walk up from project_root to find brick.json
|
|
180
|
+
brick_config_path = find_brick_json(project_root)
|
|
181
|
+
|
|
182
|
+
if brick_config_path && File.exist?(brick_config_path)
|
|
183
|
+
begin
|
|
184
|
+
config = JSON.parse(File.read(brick_config_path))
|
|
185
|
+
|
|
186
|
+
ios_path = config.dig('output', 'ios')
|
|
187
|
+
if ios_path && !ios_path.empty?
|
|
188
|
+
# Handle absolute paths (though not recommended)
|
|
189
|
+
if Pathname.new(ios_path).absolute?
|
|
190
|
+
Pod::UI.warn "[Brick] Using absolute path for iOS output is not recommended: #{ios_path}"
|
|
191
|
+
return ios_path
|
|
192
|
+
else
|
|
193
|
+
# Relative to brick.json location, not project root
|
|
194
|
+
return File.expand_path(File.join(File.dirname(brick_config_path), ios_path))
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
rescue => e
|
|
198
|
+
Pod::UI.warn "[Brick] Failed to parse brick.json: #{e.message}"
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Return default path - just the relative path, caller will resolve it
|
|
203
|
+
return 'ios/.brick'
|
|
204
|
+
end
|
|
205
|
+
|
|
101
206
|
def generate_brick_module_provider(project_root, modules)
|
|
102
207
|
return if modules.empty?
|
|
103
208
|
|
|
104
|
-
#
|
|
105
|
-
|
|
209
|
+
# Get iOS output path from brick.json
|
|
210
|
+
ios_brick_path = get_brick_ios_path(project_root)
|
|
211
|
+
|
|
212
|
+
# Handle relative vs absolute paths
|
|
213
|
+
if Pathname.new(ios_brick_path).absolute?
|
|
214
|
+
brick_dir = ios_brick_path
|
|
215
|
+
else
|
|
216
|
+
brick_dir = File.expand_path(File.join(project_root, ios_brick_path))
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Create the brick directory if it doesn't exist
|
|
106
220
|
FileUtils.mkdir_p(brick_dir) unless File.exist?(brick_dir)
|
|
107
221
|
|
|
108
222
|
# Generate imports and module instances
|