Codegen runs as part of every Android build, but you can run just that step to see what it produces before you write any Kotlin:
cd android
./gradlew :app:generateCodegenArtifactsFromSchema --no-daemon --max-workers=2
cd app/build/generated/source/codegen && find . -name "NativeBookShareSpec*"BUILD SUCCESSFUL in 1m 47s 30 actionable tasks: 2 executed, 28 up-to-date ./java/com/anonymous/booknest/share/NativeBookShareSpec.java ./jni/react/renderer/components/NativeBookShareSpec ./jni/react/renderer/components/NativeBookShareSpec/NativeBookShareSpecJSI.h ./jni/NativeBookShareSpec-generated.cpp ./jni/NativeBookShareSpec.h
The Java file is the class your Kotlin extends, an abstract NativeBookShareSpec that extends ReactContextBaseJavaModule and implements TurboModule. Read it before implementing, because it is the real contract:
@ReactMethod
@DoNotStrip
public abstract void shareBook(String title, String url, Promise promise);
@ReactMethod(isBlockingSynchronousMethod = true)
@DoNotStrip
public abstract double getShareCount();Two details surprise people. The Promise<boolean> return became a trailing Promise parameter that you settle yourself. And although the spec says CodegenTypes.Int32, React Native 0.86.3 36,878 's Codegen declared the synchronous result as a double; the C++ side, NativeBookShareSpec-generated.cpp, calls it through JNI with the signature "()D". A first Kotlin draft that returned Int would not have compiled. Never edit or commit the regenerated files under build/.