diff --git a/README.md b/README.md index c97868e..c9f0db9 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ yarn add @morrowdigital/watermelondb-expo-plugin After installing this npm package, add the [config plugin](https://docs.expo.io/guides/config-plugins/) to the [`plugins`](https://docs.expo.io/versions/latest/config/app/#plugins) array of your `app.json` or `app.config.js`. Then rebuild your app as described in the ["Adding custom native code"](https://docs.expo.io/workflow/customizing/) guide. +If you are using Proguard, add the rule to `-keep class com.nozbe.watermelondb.** { *; }` in `expo-build-properties` ## Example @@ -32,7 +33,8 @@ In your app.json `plugins` array: "expo-build-properties", { "android": { - "kotlinVersion": "1.6.10" + "kotlinVersion": "1.6.10", + "extraProguardRules": "-keep class com.nozbe.watermelondb.** { *; }" } } ] diff --git a/build/withWatermelon.js b/build/withWatermelon.js index 4b6fbdc..ec594a6 100644 --- a/build/withWatermelon.js +++ b/build/withWatermelon.js @@ -140,13 +140,68 @@ function getPlatformProjectFilePath(config, fileName) { const projectName = config.modRequest.projectName || config.name.replace(/[- ]/g, ""); return path_1.default.join(config.modRequest.platformProjectRoot, projectName, fileName); } +const withWatermelonDBAndroidJSI = (config) => { + function settingGradle(gradleConfig) { + return (0, config_plugins_1.withSettingsGradle)(gradleConfig, (mod) => { + if (!mod.modResults.contents.includes(':watermelondb-jsi')) { + mod.modResults.contents += ` + include ':watermelondb-jsi' + project(':watermelondb-jsi').projectDir = + new File(rootProject.projectDir, '../node_modules/@nozbe/watermelondb/native/android-jsi') + `; + } + return mod; + }); + } + function buildGradle(gradleConfig) { + return (0, config_plugins_1.withAppBuildGradle)(gradleConfig, (mod) => { + if (!mod.modResults.contents.includes("pickFirst '**/libc++_shared.so'")) { + mod.modResults.contents = mod.modResults.contents.replace('android {', ` + android { + packagingOptions { + pickFirst '**/libc++_shared.so' + } + `); + } + if (!mod.modResults.contents.includes("implementation project(':watermelondb-jsi')")) { + mod.modResults.contents = mod.modResults.contents.replace('dependencies {', ` + dependencies { + implementation project(':watermelondb-jsi') + `); + } + return mod; + }); + } + function mainApplication(mainAppConfig) { + return (0, config_plugins_1.withMainApplication)(mainAppConfig, (mod) => { + if (!mod.modResults.contents.includes('import com.nozbe.watermelondb.jsi.WatermelonDBJSIPackage;')) { + mod.modResults.contents = mod.modResults.contents.replace('import com.nozbe.watermelondb.WatermelonDBPackage;', ` + import com.nozbe.watermelondb.WatermelonDBPackage; + import com.nozbe.watermelondb.jsi.WatermelonDBJSIPackage; + import com.facebook.react.bridge.JSIModulePackage; + `); + } + if (!mod.modResults.contents.includes('return new WatermelonDBJSIPackage()')) { + mod.modResults.contents = mod.modResults.contents.replace('new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) {', ` + new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) { + @Override + protected JSIModulePackage getJSIModulePackage() { + return new WatermelonDBJSIPackage(); + } + `); + } + return mod; + }); + } + return mainApplication(settingGradle(buildGradle(config))); +}; // @ts-ignore exports.default = (config, options) => { // config = setAppSettingBuildGradle(config); // config = setAppBuildGradle(config); config = setAndroidMainApplication(config); config = addFlipperDb(config, options?.databases ?? []); - config = setWmelonBridgingHeader(config); + config = withWatermelonDBAndroidJSI(setWmelonBridgingHeader(config)); config = withCocoaPods(config); config = withExcludedSimulatorArchitectures(config); return config; diff --git a/package.json b/package.json index df5aa34..bf79dfd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@morrowdigital/watermelondb-expo-plugin", - "version": "2.1.2", + "version": "2.2.0", "main": "build/withWatermelon.js", "types": "build/withWatermelon.d.ts", "license": "MIT", diff --git a/src/withWatermelon.ts b/src/withWatermelon.ts index 315a2ec..2d84dd8 100644 --- a/src/withWatermelon.ts +++ b/src/withWatermelon.ts @@ -1,8 +1,12 @@ import { withXcodeProject, withDangerousMod, + withSettingsGradle, + withAppBuildGradle, + withMainApplication, ExportedConfigWithProps, } from "@expo/config-plugins"; +import { ExpoConfig } from "@expo/config-types"; import filesys from "fs"; import path from "path"; import resolveFrom from "resolve-from"; @@ -206,13 +210,96 @@ function getPlatformProjectFilePath( ); } +const withWatermelonDBAndroidJSI = (config: ExpoConfig) => { + function settingGradle(gradleConfig: ExpoConfig) { + return withSettingsGradle(gradleConfig, (mod) => { + if (!mod.modResults.contents.includes(':watermelondb-jsi')) { + mod.modResults.contents += ` + include ':watermelondb-jsi' + project(':watermelondb-jsi').projectDir = + new File(rootProject.projectDir, '../node_modules/@nozbe/watermelondb/native/android-jsi') + `; + } + return mod; + }); + } + + function buildGradle(gradleConfig: ExpoConfig) { + return withAppBuildGradle(gradleConfig, (mod) => { + if ( + !mod.modResults.contents.includes("pickFirst '**/libc++_shared.so'") + ) { + mod.modResults.contents = mod.modResults.contents.replace( + 'android {', + ` + android { + packagingOptions { + pickFirst '**/libc++_shared.so' + } + ` + ); + } + if ( + !mod.modResults.contents.includes( + "implementation project(':watermelondb-jsi')" + ) + ) { + mod.modResults.contents = mod.modResults.contents.replace( + 'dependencies {', + ` + dependencies { + implementation project(':watermelondb-jsi') + ` + ); + } + return mod; + }); + } + + function mainApplication(mainAppConfig: ExpoConfig) { + return withMainApplication(mainAppConfig, (mod) => { + if ( + !mod.modResults.contents.includes( + 'import com.nozbe.watermelondb.jsi.WatermelonDBJSIPackage;' + ) + ) { + mod.modResults.contents = mod.modResults.contents.replace( + 'import com.nozbe.watermelondb.WatermelonDBPackage;', + ` + import com.nozbe.watermelondb.WatermelonDBPackage; + import com.nozbe.watermelondb.jsi.WatermelonDBJSIPackage; + import com.facebook.react.bridge.JSIModulePackage; + ` + ); + } + if ( + !mod.modResults.contents.includes('return new WatermelonDBJSIPackage()') + ) { + mod.modResults.contents = mod.modResults.contents.replace( + 'new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) {', + ` + new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) { + @Override + protected JSIModulePackage getJSIModulePackage() { + return new WatermelonDBJSIPackage(); + } + ` + ); + } + return mod; + }); + } + + return mainApplication(settingGradle(buildGradle(config))); +}; + // @ts-ignore export default (config, options) => { // config = setAppSettingBuildGradle(config); // config = setAppBuildGradle(config); config = setAndroidMainApplication(config); config = addFlipperDb(config, options?.databases ?? []); - config = setWmelonBridgingHeader(config); + config = withWatermelonDBAndroidJSI(setWmelonBridgingHeader(config)); config = withCocoaPods(config); config = withExcludedSimulatorArchitectures(config);