Skip to content

Commit

Permalink
Add support for SDK 50 (#33)
Browse files Browse the repository at this point in the history
* Add support for SDK 50

* fix documentation

* bump version

* fix typescript errors

* Fix/support sdk 50 ios build issue (#35)

* apply old iOS configurations

* reset yarn

* add some comments

* bump version

* make ExcludeArchs, optional

* bump version

* update documentations
  • Loading branch information
killerchip authored Jan 30, 2024
1 parent b5d5802 commit 1014a12
Show file tree
Hide file tree
Showing 7 changed files with 8,453 additions and 5,464 deletions.
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,13 @@ dist/
# @end expo-cli

ios/
android/
android/

.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

52 changes: 42 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Config plugin to auto configure `@nozbe/watermelondb`

## Install

> Tested against Expo SDK 47, 48 and 49
> Tested against Expo SDK 49 and 50
```
yarn add @morrowdigital/watermelondb-expo-plugin
Expand All @@ -12,9 +12,9 @@ yarn add @morrowdigital/watermelondb-expo-plugin

> Please make sure you also install **[expo-build-properties](https://docs.expo.dev/versions/latest/sdk/build-properties/)**
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.
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 using a custom development client, 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`
You also need to add the packaging options pick-first for android.

## Example

Expand All @@ -24,24 +24,56 @@ In your app.json `plugins` array:
{
"plugins": [
[
"@morrowdigital/watermelondb-expo-plugin",
{
"databases": ["morrow.db"]
}
"@morrowdigital/watermelondb-expo-plugin"
],
[
"expo-build-properties",
{
"android": {
"kotlinVersion": "1.6.10",
"extraProguardRules": "-keep class com.nozbe.watermelondb.** { *; }"
"packagingOptions": {
"pickFirst": [
"**/libc++_shared.so"
]
}
}
}
]
]
}
```

## Guide
## JSI support for Android

This plugin installs automatically JSI support for Android builds, as per [WatermelonDB for Android instructions](https://watermelondb.dev/docs/Installation#android-react-native).
If you wish to disable JSI support during build you may add the option in config plugin:
```json
[
"@morrowdigital/watermelondb-expo-plugin",
{ "disableJSI": true }
]
```

## Build errors with M1 architectures for simulators

There have been errors building with M1 architectures for simulators on iOS, with Error:
```
No such module 'ExpoModulesCore'
```
See these discussions:
* [https://github.com/morrowdigital/watermelondb-expo-plugin/issues/20](https://github.com/morrowdigital/watermelondb-expo-plugin/issues/20)
* [https://github.com/morrowdigital/watermelondb-expo-plugin/issues/34](https://github.com/morrowdigital/watermelondb-expo-plugin/issues/34)
* [https://github.com/facebook/react-native/issues/32704#issuecomment-1174458011](https://github.com/facebook/react-native/issues/32704#issuecomment-1174458011)

This plugin will NOT add the `arm64` in `Exlcuded_Archs`, in SDK 50 builds:
```
'"EXCLUDED_ARCHS[sdk=iphonesimulator*]"'] = '"arm64"'
```

We've written a more detailed guide on how to use this plugin within your project: https://www.themorrow.digital/blog/how-to-use-watermelondb-with-react-native-expo
If you wish to add the above in configuration, you can add it with option:
```json
[
"@morrowdigital/watermelondb-expo-plugin",
{ "excludeSimArch": true }
]
```
7 changes: 7 additions & 0 deletions build/withWatermelon.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
import { ExpoConfig } from "@expo/config-types";
type Options = {
disableJsi?: boolean;
databases?: string[];
excludeSimArch?: boolean;
};
export declare function withSDK50(options: Options): (config: ExpoConfig) => ExpoConfig;
declare const _default: (config: any, options: any) => any;
export default _default;
130 changes: 109 additions & 21 deletions build/withWatermelon.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,99 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.withSDK50 = void 0;
const config_plugins_1 = require("@expo/config-plugins");
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const resolve_from_1 = __importDefault(require("resolve-from"));
const insertLinesHelper_1 = require("./insertLinesHelper");
const fs = fs_1.default.promises;
/**
* Platform: Android
* Version 50+
* */
function setAndroidMainApplication(config) {
return (0, config_plugins_1.withDangerousMod)(config, [
"android",
async (config) => {
// @ts-ignore
const extension = config.sdkVersion >= '50.0.0' ? 'kt' : 'java';
const root = config.modRequest.platformProjectRoot;
const filePath = `${root}/app/src/main/java/${config?.android?.package?.replace(/\./g, "/")}/MainApplication.java`;
const filePath = `${root}/app/src/main/java/${config?.android?.package?.replace(/\./g, "/")}/MainApplication.${extension}`;
const contents = await fs.readFile(filePath, "utf-8");
let updated = (0, insertLinesHelper_1.insertLinesHelper)("import com.nozbe.watermelondb.WatermelonDBPackage;", "import java.util.List;", contents);
await fs.writeFile(filePath, updated);
return 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(config) {
return (0, config_plugins_1.withAppBuildGradle)(config, (mod) => {
const newContents = mod.modResults.contents.replace('dependencies {', `dependencies {
implementation project(':watermelondb-jsi')
`);
mod.modResults.contents = newContents;
return mod;
});
}
const cocoaPods = (config) => {
return (0, config_plugins_1.withDangerousMod)(config, [
"ios",
async (config) => {
const filePath = path_1.default.join(config.modRequest.platformProjectRoot, "Podfile");
const contents = await fs.readFile(filePath, "utf-8");
const newContents = contents.replace('post_install do |installer|', `
# WatermelonDB dependency
pod 'simdjson', path: '../node_modules/@nozbe/simdjson', modular_headers: true
post_install do |installer|`);
await fs.writeFile(filePath, newContents);
return config;
},
]);
};
function mainApplication(config) {
return (0, config_plugins_1.withMainApplication)(config, (mod) => {
mod.modResults['contents'] = mod.modResults.contents.replace('import android.app.Application', `
import android.app.Application
import com.nozbe.watermelondb.jsi.WatermelonDBJSIPackage;
import com.facebook.react.bridge.JSIModulePackage;
`);
const newContents2 = mod.modResults.contents.replace('override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED', `
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
override fun getJSIModulePackage(): JSIModulePackage {
return WatermelonDBJSIPackage()
}`);
mod.modResults.contents = newContents2;
return mod;
});
}
function proGuardRules(config) {
return (0, config_plugins_1.withDangerousMod)(config, ['android', async (config) => {
const contents = await fs.readFile(`${config.modRequest.platformProjectRoot}/app/proguard-rules.pro`, 'utf-8');
const newContents = `
${contents}
-keep class com.nozbe.watermelondb.** { *; }
`;
await fs.writeFile(`${config.modRequest.platformProjectRoot}/app/proguard-rules.pro`, newContents);
return config;
}]);
}
/**
* Version 50+ finish
* */
/**
* Platform: Android
* */
Expand Down Expand Up @@ -140,19 +211,11 @@ 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;
});
const withWatermelonDBAndroidJSI = (config, options) => {
if (options?.disableJsi === true) {
return config;
}
;
function buildGradle(gradleConfig) {
return (0, config_plugins_1.withAppBuildGradle)(gradleConfig, (mod) => {
if (!mod.modResults.contents.includes("pickFirst '**/libc++_shared.so'")) {
Expand Down Expand Up @@ -196,13 +259,38 @@ const withWatermelonDBAndroidJSI = (config) => {
return mainApplication(settingGradle(buildGradle(config)));
};
// @ts-ignore
function withSDK50(options) {
return (config) => {
let currentConfig = config;
// Android
if (options?.disableJsi !== true) {
currentConfig = settingGradle(config);
currentConfig = buildGradle(currentConfig);
currentConfig = proGuardRules(currentConfig);
currentConfig = mainApplication(currentConfig);
}
// iOS
currentConfig = setWmelonBridgingHeader(currentConfig);
currentConfig = withCocoaPods(currentConfig);
if (options?.excludeSimArch === true) {
currentConfig = withExcludedSimulatorArchitectures(currentConfig);
}
return currentConfig;
};
}
exports.withSDK50 = withSDK50;
// @ts-ignore
exports.default = (config, options) => {
// config = setAppSettingBuildGradle(config);
// config = setAppBuildGradle(config);
config = setAndroidMainApplication(config);
config = addFlipperDb(config, options?.databases ?? []);
config = withWatermelonDBAndroidJSI(setWmelonBridgingHeader(config));
config = withCocoaPods(config);
config = withExcludedSimulatorArchitectures(config);
if (config.sdkVersion >= '50.0.0') {
return withSDK50(options)(config);
}
;
if (config.sdkVersion < '50.0.0') {
config = setAndroidMainApplication(config);
config = addFlipperDb(config, options?.databases ?? []);
config = withWatermelonDBAndroidJSI(setWmelonBridgingHeader(config), options);
config = withCocoaPods(config);
config = withExcludedSimulatorArchitectures(config);
}
return config;
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@morrowdigital/watermelondb-expo-plugin",
"version": "2.2.0-beta.0",
"version": "2.3.0",
"main": "build/withWatermelon.js",
"types": "build/withWatermelon.d.ts",
"license": "MIT",
Expand All @@ -15,7 +15,7 @@
"expo"
],
"devDependencies": {
"@expo/config-plugins": "^6.0.1",
"@expo/config-plugins": "^7.8.4",
"expo-module-scripts": "^3.0.7"
},
"files": [
Expand Down
Loading

0 comments on commit 1014a12

Please sign in to comment.