brick-module 0.4.0 → 0.5.0
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.
|
@@ -102,7 +102,7 @@ ext.isBrickModule = { packageJson ->
|
|
|
102
102
|
return packageJson?.brickModule != null
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
ext.runBrickCodegen = { workingDir ->
|
|
105
|
+
ext.runBrickCodegen = { workingDir, options = [:] ->
|
|
106
106
|
def brickModuleDir = resolveModule(workingDir, "brick-module")
|
|
107
107
|
if (brickModuleDir == null) {
|
|
108
108
|
brickLog("brick-module not found, skipping code generation")
|
|
@@ -117,7 +117,18 @@ ext.runBrickCodegen = { workingDir ->
|
|
|
117
117
|
|
|
118
118
|
try {
|
|
119
119
|
def wdPath = (workingDir instanceof File) ? workingDir.absolutePath : workingDir
|
|
120
|
-
def
|
|
120
|
+
def codegenArgs = [
|
|
121
|
+
'node',
|
|
122
|
+
codegenPath.absolutePath,
|
|
123
|
+
'--platform',
|
|
124
|
+
'android',
|
|
125
|
+
'--projectRoot',
|
|
126
|
+
wdPath
|
|
127
|
+
]
|
|
128
|
+
if (options.noClean == true) {
|
|
129
|
+
codegenArgs.add('--no-clean')
|
|
130
|
+
}
|
|
131
|
+
def proc = codegenArgs.execute(null, workingDir)
|
|
121
132
|
proc.waitFor()
|
|
122
133
|
return proc.exitValue() == 0
|
|
123
134
|
} catch (Exception e) {
|
|
@@ -217,10 +228,12 @@ ext.applyBrickModules = { settings, args ->
|
|
|
217
228
|
def androidBrickPath = getBrickAndroidPath(projectRoot)
|
|
218
229
|
def brickDir = new File(androidBrickPath)
|
|
219
230
|
def needsCodegen = !brickDir.exists() || !new File(brickDir, "src/main/kotlin/BrickModule.kt").exists()
|
|
220
|
-
|
|
231
|
+
def codegenAttempted = false
|
|
221
232
|
if (needsCodegen) {
|
|
222
|
-
|
|
233
|
+
codegenAttempted = true
|
|
234
|
+
runBrickCodegen(projectRoot, [noClean: true])
|
|
223
235
|
}
|
|
236
|
+
settings.ext.brickCodegenRan = codegenAttempted
|
|
224
237
|
|
|
225
238
|
// Include generated module (use configured path)
|
|
226
239
|
if (brickDir.exists()) {
|
|
@@ -239,6 +252,8 @@ ext.applyBrickModules = { settings, args ->
|
|
|
239
252
|
gradle.rootProject.ext.brickModulesList = foundModules
|
|
240
253
|
gradle.rootProject.ext.brickProjectRoot = projectRoot
|
|
241
254
|
gradle.rootProject.ext.brickAppProjectName = appProjectName
|
|
255
|
+
gradle.rootProject.ext.brickCodegenRanInBuild =
|
|
256
|
+
settings.ext.has("brickCodegenRan") ? settings.ext.brickCodegenRan : false
|
|
242
257
|
configureAppProject(gradle)
|
|
243
258
|
// Inline: ensure RN autolinking doesn't fail due to missing codegen/jni for brick-module
|
|
244
259
|
gradle.rootProject.subprojects { subproj ->
|
|
@@ -418,24 +433,16 @@ ${moduleNames}
|
|
|
418
433
|
project.preBuild.dependsOn('generateBrickModulesList')
|
|
419
434
|
project.preBuild.doFirst {
|
|
420
435
|
def workingDir = projectRoot
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
def brickOutputDir = getBrickAndroidPath(workingDir)
|
|
427
|
-
def generatedMarker = new File(brickOutputDir, "src/main/kotlin/BrickModule.kt")
|
|
428
|
-
def androidAppPath = getBrickAndroidAppPath(workingDir)
|
|
429
|
-
def jniDir = new File(androidAppPath, "build/generated/autolinking/src/main/jni")
|
|
430
|
-
def hasJniOutputs = new File(jniDir, "BrickModuleSpec-generated.cpp").exists() &&
|
|
431
|
-
new File(jniDir, "BrickModuleSpec.h").exists() &&
|
|
432
|
-
new File(jniDir, "CMakeLists.txt").exists()
|
|
433
|
-
if (generatedMarker.exists() && hasJniOutputs) {
|
|
434
|
-
// Already generated, skip to preserve build outputs
|
|
436
|
+
|
|
437
|
+
def alreadyRan = rootProject.ext.has("brickCodegenRanInBuild") ?
|
|
438
|
+
rootProject.ext.brickCodegenRanInBuild : false
|
|
439
|
+
if (alreadyRan) {
|
|
440
|
+
// Avoid double-running if settings already executed codegen.
|
|
435
441
|
return
|
|
436
442
|
}
|
|
443
|
+
rootProject.ext.brickCodegenRanInBuild = true
|
|
437
444
|
|
|
438
|
-
// Run codegen
|
|
445
|
+
// Run codegen once per build without cleaning outputs.
|
|
439
446
|
try {
|
|
440
447
|
def proc = ['node', '-p', "require.resolve('brick-module/package.json')"].execute(null, workingDir)
|
|
441
448
|
proc.waitFor()
|
|
@@ -447,10 +454,15 @@ ${moduleNames}
|
|
|
447
454
|
def codegenPath = new File(brickModuleDir, "bin/brick-codegen.js")
|
|
448
455
|
|
|
449
456
|
if (codegenPath.exists()) {
|
|
450
|
-
def codegenArgs = [
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
457
|
+
def codegenArgs = [
|
|
458
|
+
'node',
|
|
459
|
+
codegenPath.absolutePath,
|
|
460
|
+
'--platform',
|
|
461
|
+
'android',
|
|
462
|
+
'--projectRoot',
|
|
463
|
+
workingDir.absolutePath,
|
|
464
|
+
'--no-clean'
|
|
465
|
+
]
|
|
454
466
|
def codegenProc = codegenArgs.execute(null, workingDir)
|
|
455
467
|
codegenProc.waitFor()
|
|
456
468
|
}
|
|
@@ -3,33 +3,45 @@ package com.brickmodule
|
|
|
3
3
|
import com.facebook.react.bridge.*
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Helper class for converting data to React Native compatible formats
|
|
7
|
-
*
|
|
6
|
+
* Helper class for converting data to React Native compatible formats Ensures type safety when
|
|
7
|
+
* sending events to JavaScript
|
|
8
8
|
*/
|
|
9
9
|
object EventDataConverter {
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
private fun isNullSentinel(value: Any?): Boolean {
|
|
12
|
+
return value is Null ||
|
|
13
|
+
(value != null && value.javaClass.name == "com.brickmodule.Null") ||
|
|
14
|
+
(value is String && value.startsWith("com.brickmodule.Null@"))
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
/**
|
|
12
18
|
* Convert any data to React Native compatible format
|
|
13
|
-
*
|
|
19
|
+
*
|
|
14
20
|
* @param data The data to convert
|
|
15
21
|
* @return React Native compatible data or null if conversion fails
|
|
16
22
|
*/
|
|
17
23
|
fun convert(data: Any?): Any? {
|
|
18
24
|
return try {
|
|
19
|
-
|
|
20
|
-
null
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
data.
|
|
25
|
+
if (isNullSentinel(data)) {
|
|
26
|
+
null
|
|
27
|
+
} else {
|
|
28
|
+
when (data) {
|
|
29
|
+
null -> null
|
|
30
|
+
is String -> data
|
|
31
|
+
is Boolean -> data
|
|
32
|
+
is Int -> data
|
|
33
|
+
is Double -> data
|
|
34
|
+
is Float -> data.toDouble()
|
|
35
|
+
is Long -> data.toDouble()
|
|
36
|
+
is Map<*, *> -> convertMap(data)
|
|
37
|
+
is List<*> -> convertList(data)
|
|
38
|
+
is Array<*> -> convertList(data.toList())
|
|
39
|
+
else -> {
|
|
40
|
+
println(
|
|
41
|
+
"⚠️ EventDataConverter: Unsupported data type ${data.javaClass.simpleName}, converting to string"
|
|
42
|
+
)
|
|
43
|
+
data.toString()
|
|
44
|
+
}
|
|
33
45
|
}
|
|
34
46
|
}
|
|
35
47
|
} catch (e: Exception) {
|
|
@@ -37,17 +49,17 @@ object EventDataConverter {
|
|
|
37
49
|
null
|
|
38
50
|
}
|
|
39
51
|
}
|
|
40
|
-
|
|
52
|
+
|
|
41
53
|
/**
|
|
42
54
|
* Convert a map to WritableMap for React Native
|
|
43
|
-
*
|
|
55
|
+
*
|
|
44
56
|
* @param map The map to convert
|
|
45
57
|
* @return WritableMap or null if conversion fails
|
|
46
58
|
*/
|
|
47
59
|
private fun convertMap(map: Map<*, *>): WritableMap? {
|
|
48
60
|
return try {
|
|
49
61
|
val writableMap = Arguments.createMap()
|
|
50
|
-
|
|
62
|
+
|
|
51
63
|
map.forEach { (key, value) ->
|
|
52
64
|
val keyString = key?.toString()
|
|
53
65
|
if (keyString != null) {
|
|
@@ -63,24 +75,24 @@ object EventDataConverter {
|
|
|
63
75
|
}
|
|
64
76
|
}
|
|
65
77
|
}
|
|
66
|
-
|
|
78
|
+
|
|
67
79
|
writableMap
|
|
68
80
|
} catch (e: Exception) {
|
|
69
81
|
println("❌ EventDataConverter: Failed to convert map: ${e.message}")
|
|
70
82
|
null
|
|
71
83
|
}
|
|
72
84
|
}
|
|
73
|
-
|
|
85
|
+
|
|
74
86
|
/**
|
|
75
87
|
* Convert a list to WritableArray for React Native
|
|
76
|
-
*
|
|
88
|
+
*
|
|
77
89
|
* @param list The list to convert
|
|
78
90
|
* @return WritableArray or null if conversion fails
|
|
79
91
|
*/
|
|
80
92
|
private fun convertList(list: List<*>): WritableArray? {
|
|
81
93
|
return try {
|
|
82
94
|
val writableArray = Arguments.createArray()
|
|
83
|
-
|
|
95
|
+
|
|
84
96
|
list.forEach { item ->
|
|
85
97
|
when (val convertedValue = convert(item)) {
|
|
86
98
|
null -> writableArray.pushNull()
|
|
@@ -93,30 +105,31 @@ object EventDataConverter {
|
|
|
93
105
|
else -> writableArray.pushString(convertedValue.toString())
|
|
94
106
|
}
|
|
95
107
|
}
|
|
96
|
-
|
|
108
|
+
|
|
97
109
|
writableArray
|
|
98
110
|
} catch (e: Exception) {
|
|
99
111
|
println("❌ EventDataConverter: Failed to convert list: ${e.message}")
|
|
100
112
|
null
|
|
101
113
|
}
|
|
102
114
|
}
|
|
103
|
-
|
|
115
|
+
|
|
104
116
|
/**
|
|
105
117
|
* Validate if data can be safely converted to React Native format
|
|
106
|
-
*
|
|
118
|
+
*
|
|
107
119
|
* @param data The data to validate
|
|
108
120
|
* @return true if data can be safely converted, false otherwise
|
|
109
121
|
*/
|
|
110
122
|
fun isConvertible(data: Any?): Boolean {
|
|
123
|
+
if (isNullSentinel(data)) {
|
|
124
|
+
return true
|
|
125
|
+
}
|
|
111
126
|
return when (data) {
|
|
112
127
|
null -> true
|
|
113
128
|
is String, is Boolean, is Number -> true
|
|
114
|
-
is Map<*, *> -> data.all { (key, value) ->
|
|
115
|
-
key is String && isConvertible(value)
|
|
116
|
-
}
|
|
129
|
+
is Map<*, *> -> data.all { (key, value) -> key is String && isConvertible(value) }
|
|
117
130
|
is List<*> -> data.all { isConvertible(it) }
|
|
118
131
|
is Array<*> -> data.all { isConvertible(it) }
|
|
119
132
|
else -> false
|
|
120
133
|
}
|
|
121
134
|
}
|
|
122
|
-
}
|
|
135
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,16 @@ import { Any, AnyObject } from "./types.js";
|
|
|
4
4
|
|
|
5
5
|
//#region src/index.d.ts
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Error types for Brick modules
|
|
9
|
+
* @deprecated Use BrickError instead
|
|
10
|
+
*/
|
|
11
|
+
declare class BrickModuleError extends Error {
|
|
12
|
+
code: string;
|
|
13
|
+
moduleName?: string | undefined;
|
|
14
|
+
methodName?: string | undefined;
|
|
15
|
+
constructor(message: string, code?: string, moduleName?: string | undefined, methodName?: string | undefined);
|
|
16
|
+
}
|
|
7
17
|
/**
|
|
8
18
|
* Configuration interface for brick-codegen
|
|
9
19
|
*/
|
|
@@ -21,4 +31,4 @@ interface BrickCodegenConfig {
|
|
|
21
31
|
dev?: boolean;
|
|
22
32
|
}
|
|
23
33
|
//#endregion
|
|
24
|
-
export { Any, AnyObject, BrickCodegenConfig, BrickError, BrickModule, type BrickModuleInterface, type BrickModuleSpec };
|
|
34
|
+
export { Any, AnyObject, BrickCodegenConfig, BrickError, BrickModule, BrickModuleError, type BrickModuleInterface, type BrickModuleSpec };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
import { BrickError } from "./BrickError.js";
|
|
2
2
|
import BrickModule_default from "./BrickModule.js";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
//#region src/index.ts
|
|
5
|
+
/**
|
|
6
|
+
* Error types for Brick modules
|
|
7
|
+
* @deprecated Use BrickError instead
|
|
8
|
+
*/
|
|
9
|
+
var BrickModuleError = class extends Error {
|
|
10
|
+
constructor(message, code = "BRICK_ERROR", moduleName, methodName) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.moduleName = moduleName;
|
|
14
|
+
this.methodName = methodName;
|
|
15
|
+
this.name = "BrickModuleError";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
export { BrickError, BrickModule_default as BrickModule, BrickModuleError };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brick-module",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Better React Native native module development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"brick-codegen": "./bin/brick-codegen.js"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"brick-codegen": "0.
|
|
61
|
+
"brick-codegen": "0.5.0"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"react": ">=18.2.0",
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,22 @@ export type { BrickModuleInterface, BrickModuleSpec } from "./BrickModule";
|
|
|
6
6
|
export { default as BrickModule } from "./BrickModule";
|
|
7
7
|
export { BrickError } from "./BrickError";
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Error types for Brick modules
|
|
11
|
+
* @deprecated Use BrickError instead
|
|
12
|
+
*/
|
|
13
|
+
export class BrickModuleError extends Error {
|
|
14
|
+
constructor(
|
|
15
|
+
message: string,
|
|
16
|
+
public code: string = "BRICK_ERROR",
|
|
17
|
+
public moduleName?: string,
|
|
18
|
+
public methodName?: string
|
|
19
|
+
) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "BrickModuleError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
9
25
|
/**
|
|
10
26
|
* Configuration interface for brick-codegen
|
|
11
27
|
*/
|