Port an Expo Module
Keep the TypeScript API, and write the Swift and Kotlin bodies as the two branches of one Lucent module.
- Copy the module's TypeScript API: its exported functions, types and enums. That's your module's export list.
- For each function, take the Swift and the Kotlin body and write them as the two branches of one Lucent function,
if (PLATFORM === "ios") { … } else { … }. - Keep the SDK calls; change the syntax. Swift's names work as they are, nested types join with
_, and Kotlin's getters are properties. - Replace
AsyncFunction(…).runOnQueue(.main)with anasyncfunction whose SDK calls sit inmain(). - Replace
throw Exception(…)withthrow error("ERR_CODE", message), keeping the original's codes, so JavaScript can test them. - Replace events (
sendEvent) with a callback parameter and a stop function. See Send events to JavaScript. - Delete the Swift, the Kotlin, the podspec, the Gradle file and
expo-module.config.json. Point the JavaScript imports at the.lucentmodule.
AsyncFunction("hasStringAsync") { () -> Bool in UIPasteboard.general.hasStrings}import { PLATFORM } from "lucent:platform";import { UIPasteboard } from "lucent:ios/UIKit";import { ClipboardManager, ClipDescription } from "lucent:android/android.content";import { appContext } from "lucent:android";import { main } from "lucent:thread";
export async function hasStringAsync(): Promise<boolean> { if (PLATFORM === "ios") { return UIPasteboard.general.hasStrings; } else { return main(() => { const manager = appContext().getSystemService(ClipboardManager); return ( manager?.getPrimaryClipDescription()?.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN) ?? false ); }); }}Test the port next to the original: call both from one screen and compare. The examples are ports of six Expo and community modules, each checked this way.