From 95dd32e908cf09cc949e8c96e5e2f6e750f6cac2 Mon Sep 17 00:00:00 2001 From: Wojtach Date: Fri, 27 Jun 2025 18:03:07 +0200 Subject: [PATCH 1/2] feat: added way to build without ee features --- android/build.gradle | 2 +- android/src/main/java/com/cblreactnative/DataAdapter.kt | 5 ++++- android/src/main/java/com/cblreactnative/cbl-js-kotlin | 2 +- cbl-reactnative.podspec | 2 +- ios/cbl-js-swift | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 6e42986..bce1550 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -107,7 +107,7 @@ dependencies { implementation "com.facebook.react:react-native:+" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.json:json:20240303" - implementation "com.couchbase.lite:couchbase-lite-android-ee-ktx:3.2.1" + implementation "com.couchbase.lite:couchbase-lite-android-ktx:3.2.1" implementation 'com.eclipsesource.j2v8:j2v8:6.2.1@aar' } diff --git a/android/src/main/java/com/cblreactnative/DataAdapter.kt b/android/src/main/java/com/cblreactnative/DataAdapter.kt index e196557..9739d11 100644 --- a/android/src/main/java/com/cblreactnative/DataAdapter.kt +++ b/android/src/main/java/com/cblreactnative/DataAdapter.kt @@ -16,6 +16,7 @@ import java.util.Date import java.util.Locale import java.util.TimeZone import com.couchbase.lite.Collection as CBLCollection +import com.cblreactnative.CouchbaseReflectionHelper object DataAdapter { @@ -376,10 +377,12 @@ object DataAdapter { target = endpoint, continuous = continuous, acceptParentDomainCookies = acceptParentDomainCookies, - acceptOnlySelfSignedServerCertificate = acceptSelfSignedCerts, enableAutoPurge = autoPurgeEnabled, type = replicatorType, ) + + CouchbaseReflectionHelper.setAcceptOnlySelfSignedServerCertificate(configBuilder, acceptSelfSignedCerts) + val authenticatorMap = map.getMap("authenticator") authenticatorMap?.let { val authenticator = readableMapToAuthenticator(it) diff --git a/android/src/main/java/com/cblreactnative/cbl-js-kotlin b/android/src/main/java/com/cblreactnative/cbl-js-kotlin index c4e3f7d..6b786be 160000 --- a/android/src/main/java/com/cblreactnative/cbl-js-kotlin +++ b/android/src/main/java/com/cblreactnative/cbl-js-kotlin @@ -1 +1 @@ -Subproject commit c4e3f7d7c6dd4c2b1dfcaf404c9c19f78ae9fb0a +Subproject commit 6b786be77d11629ce6a66ec914e242dcbe46c9ad diff --git a/cbl-reactnative.podspec b/cbl-reactnative.podspec index 739acf4..08aca39 100644 --- a/cbl-reactnative.podspec +++ b/cbl-reactnative.podspec @@ -15,7 +15,7 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/Couchbase-Ecosystem/cbl-reactnative", :tag => "#{s.version}" } s.swift_version = '5.5' - s.dependency 'CouchbaseLite-Swift-Enterprise', '3.2.1' + s.dependency 'CouchbaseLite-Swift', '3.2.1' s.source_files = "ios/**/*.{h,m,mm,swift}" # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0. diff --git a/ios/cbl-js-swift b/ios/cbl-js-swift index d2040e6..9429312 160000 --- a/ios/cbl-js-swift +++ b/ios/cbl-js-swift @@ -1 +1 @@ -Subproject commit d2040e6a39a9bf40f085a3c790e08eedf7820a41 +Subproject commit 9429312c80fba68bc2f803f3155912324f23910c From e58ce896506d4dd19a3e9d8fe0a7561795051c12 Mon Sep 17 00:00:00 2001 From: Wojtach Date: Fri, 27 Jun 2025 18:31:03 +0200 Subject: [PATCH 2/2] feat: script for changing editions --- .eslintignore | 5 +- README.md | 17 ++- app.plugin.js | 1 + cbl-edition.json | 5 + expo-example/.gitignore | 4 +- expo-example/app.json | 5 +- expo-example/package-lock.json | 5 +- package.json | 11 +- plugin/src/withCouchbaseLite.js | 119 +++++++++++++++++ scripts/configure-edition.js | 218 ++++++++++++++++++++++++++++++++ 10 files changed, 382 insertions(+), 8 deletions(-) create mode 100644 app.plugin.js create mode 100644 cbl-edition.json create mode 100644 plugin/src/withCouchbaseLite.js create mode 100755 scripts/configure-edition.js diff --git a/.eslintignore b/.eslintignore index 9d0d873..8d8d9c0 100644 --- a/.eslintignore +++ b/.eslintignore @@ -6,4 +6,7 @@ dist/ lib/ src/cblite-js ios/ -bable.config.js \ No newline at end of file +bable.config.js +scripts/ +plugin/ +app.plugin.js diff --git a/README.md b/README.md index 4d18ff1..edf16b5 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,20 @@ This module currently uses the stable technologies defined by the legacy archite This project is still a work in progress and is not officially supported by Couchbase. This is an open source project, to check the status of the project, navigate to the project's board on [GitHub - Project Status](https://github.com/orgs/Couchbase-Ecosystem/projects/2) ## Installation + The project has full documentation on how to set up and use the Native Module at [cbl-reactnative.dev](https://cbl-reactnative.dev) under the Start Here! -> Install section. +### Configure Edition + +After installing the package, configure your edition: + +```bash +# For Community Edition (default) +npx cbl-reactnative-configure CE + +# For Enterprise Edition +npx cbl-reactnative-configure EE + ## Contributing See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. @@ -26,10 +38,11 @@ The project has full documentation of the API at [cbl-reactnative.dev](https://c ## šŸ“¢ Support Policy -We truly appreciate your interest in this project! +We truly appreciate your interest in this project! This project is **community-maintained**, which means it's **not officially supported** by our support team. -If you need help, have found a bug, or want to contribute improvements, the best place to do that is right here — by [opening a GitHub issue](https://github.com/Couchbase-Ecosystem/cbl-reactnative/issues). +If you need help, have found a bug, or want to contribute improvements, the best place to do that is right here — by [opening a GitHub issue](https://github.com/Couchbase-Ecosystem/cbl-reactnative/issues). Our support portal is unable to assist with requests related to this project, so we kindly ask that all inquiries stay within GitHub. Your collaboration helps us all move forward together — thank you! +``` diff --git a/app.plugin.js b/app.plugin.js new file mode 100644 index 0000000..bb8c299 --- /dev/null +++ b/app.plugin.js @@ -0,0 +1 @@ +module.exports = require('./plugin/src/withCouchbaseLite'); diff --git a/cbl-edition.json b/cbl-edition.json new file mode 100644 index 0000000..dc254ef --- /dev/null +++ b/cbl-edition.json @@ -0,0 +1,5 @@ +{ + "edition": "CE", + "version": "3.2.1", + "timestamp": "2024-01-01T00:00:00.000Z" +} diff --git a/expo-example/.gitignore b/expo-example/.gitignore index 0b37b6e..ccc15e6 100644 --- a/expo-example/.gitignore +++ b/expo-example/.gitignore @@ -38,4 +38,6 @@ yarn-error.* # The following patterns were generated by expo-cli expo-env.d.ts -# @end expo-cli \ No newline at end of file +# @end expo-cli +# Couchbase Lite configuration +cbl-edition.json diff --git a/expo-example/app.json b/expo-example/app.json index d4b0a20..256ce98 100644 --- a/expo-example/app.json +++ b/expo-example/app.json @@ -27,10 +27,11 @@ "plugins": [ "expo-router", "./cbl-reactnative-plugin.js", - "expo-font" + "expo-font", + "cbl-reactnative" ], "experiments": { "typedRoutes": true } } -} +} \ No newline at end of file diff --git a/expo-example/package-lock.json b/expo-example/package-lock.json index 3fdfd51..3feac6a 100644 --- a/expo-example/package-lock.json +++ b/expo-example/package-lock.json @@ -51,7 +51,7 @@ }, "..": { "name": "cbl-reactnative", - "version": "0.6.0", + "version": "0.6.1", "license": "Apache-2.0", "workspaces": [ "example" @@ -59,6 +59,9 @@ "dependencies": { "react-native-uuid": "^2.0.2" }, + "bin": { + "cbl-reactnative-configure": "scripts/configure-edition.js" + }, "devDependencies": { "@commitlint/config-conventional": "^17.8.1", "@evilmartians/lefthook": "^1.8.4", diff --git a/package.json b/package.json index 2a8dad3..11c0672 100644 --- a/package.json +++ b/package.json @@ -23,13 +23,18 @@ "type": "git", "url": "git+https://github.com/Couchbase-Ecosystem/cbl-reactnative.git" }, + "bin": { + "cbl-reactnative-configure": "./scripts/configure-edition.js" + }, "scripts": { "test": "jest", "typecheck": "tsc --noEmit", "lint": "eslint \"**/*.{js,ts,tsx}\"", "clean": "del-cli android/build expo-example/android/build expo-example/android/app/build expo-example/ios/build lib", "build": "bob build", - "release": "release-it" + "release": "release-it", + "configure:ce": "node scripts/configure-edition.js CE", + "configure:ee": "node scripts/configure-edition.js EE" }, "main": "./lib/commonjs/index.js", "source": "./src/index.tsx", @@ -48,6 +53,10 @@ "android", "ios", "cpp", + "plugin", + "scripts", + "app.plugin.js", + "cbl-edition.json", "*.podspec", "!ios/build", "!android/build", diff --git a/plugin/src/withCouchbaseLite.js b/plugin/src/withCouchbaseLite.js new file mode 100644 index 0000000..e0b7d40 --- /dev/null +++ b/plugin/src/withCouchbaseLite.js @@ -0,0 +1,119 @@ +const { withDangerousMod, withPlugins } = require('@expo/config-plugins'); +const { withAppBuildGradle } = require('@expo/config-plugins'); +const fs = require('fs'); +const path = require('path'); + +const EDITIONS = { + CE: { + android: 'com.couchbase.lite:couchbase-lite-android-ktx', + ios: 'CouchbaseLite-Swift', + }, + EE: { + android: 'com.couchbase.lite:couchbase-lite-android-ee-ktx', + ios: 'CouchbaseLite-Enterprise-Swift', + }, +}; + +const VERSION = '3.2.1'; + +function readEditionConfig(projectRoot) { + try { + const configPath = path.join(projectRoot, 'cbl-edition.json'); + if (fs.existsSync(configPath)) { + const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); + return config.edition || 'CE'; + } + } catch (error) { + console.log('No cbl-edition.json found, using default CE edition'); + } + return 'CE'; +} + +const withCouchbaseLiteAndroid = (config, { edition }) => { + return withAppBuildGradle(config, (config) => { + const dependency = EDITIONS[edition].android; + + config.modResults.contents = config.modResults.contents.replace( + /dependencies\s*{/, + `dependencies { + // Couchbase Lite Edition Override + configurations.all { + resolutionStrategy { + force "${dependency}:${VERSION}" + } + } +` + ); + + return config; + }); +}; + +const withCouchbaseLiteIOS = (config, { edition }) => { + return withDangerousMod(config, [ + 'ios', + async (config) => { + const dependency = EDITIONS[edition].ios; + const podfilePath = path.join( + config.modRequest.platformProjectRoot, + 'Podfile' + ); + + if (fs.existsSync(podfilePath)) { + let podfile = fs.readFileSync(podfilePath, 'utf8'); + + // Remove any existing Couchbase pod overrides + podfile = podfile.replace( + /\n\s*# Couchbase Lite Edition Override[\s\S]*?pod 'CouchbaseLite[^']*'[^\n]*\n/g, + '' + ); + + // Add the correct pod + const podOverride = `\n # Couchbase Lite Edition Override\n pod '${dependency}', '${VERSION}', :modular_headers => true\n`; + + // Add before use_react_native! + podfile = podfile.replace(/(use_react_native!)/, `${podOverride} $1`); + + // Add EE source if needed + if (edition === 'EE') { + if ( + !podfile.includes( + 'https://github.com/couchbase/couchbase-lite-ios-ee.git' + ) + ) { + podfile = `source 'https://github.com/couchbase/couchbase-lite-ios-ee.git'\n${podfile}`; + } + } + + fs.writeFileSync(podfilePath, podfile); + } + + return config; + }, + ]); +}; + +function withCouchbaseLite(config, props = {}) { + // First try to read from props, then from config file + let edition = props.edition; + + if (!edition) { + const projectRoot = config._internal?.projectRoot || process.cwd(); + edition = readEditionConfig(projectRoot); + } + + edition = edition?.toUpperCase() || 'CE'; + + if (!EDITIONS[edition]) { + throw new Error( + `Invalid Couchbase Lite edition: ${edition}. Use 'CE' or 'EE'.` + ); + } + + return withPlugins(config, [ + [withCouchbaseLiteAndroid, { edition }], + [withCouchbaseLiteIOS, { edition }], + ]); +} + +module.exports = withCouchbaseLite; diff --git a/scripts/configure-edition.js b/scripts/configure-edition.js new file mode 100755 index 0000000..5badd40 --- /dev/null +++ b/scripts/configure-edition.js @@ -0,0 +1,218 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +const EDITIONS = { + CE: { + android: 'com.couchbase.lite:couchbase-lite-android-ktx', + ios: 'CouchbaseLite-Swift', + name: 'Community', + }, + EE: { + android: 'com.couchbase.lite:couchbase-lite-android-ee-ktx', + ios: 'CouchbaseLite-Enterprise-Swift', + name: 'Enterprise', + }, +}; + +function findProjectRoot() { + let currentDir = process.cwd(); + + // If we're in node_modules, go up to the project root + if (currentDir.includes('node_modules')) { + while (currentDir.includes('node_modules')) { + currentDir = path.dirname(currentDir); + } + return currentDir; + } + + // Otherwise, look for package.json + while (currentDir !== '/') { + if (fs.existsSync(path.join(currentDir, 'package.json'))) { + const pkg = JSON.parse( + fs.readFileSync(path.join(currentDir, 'package.json'), 'utf8') + ); + if ( + pkg.dependencies?.['react-native'] || + pkg.devDependencies?.['react-native'] + ) { + return currentDir; + } + } + currentDir = path.dirname(currentDir); + } + + return process.cwd(); +} + +function detectProjectType(projectRoot) { + const hasAppJson = fs.existsSync(path.join(projectRoot, 'app.json')); + const hasAppConfig = fs.existsSync(path.join(projectRoot, 'app.config.js')); + const hasExpoPackage = (() => { + try { + const pkg = JSON.parse( + fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8') + ); + return !!(pkg.dependencies?.expo || pkg.devDependencies?.expo); + } catch { + return false; + } + })(); + + return hasAppJson || hasAppConfig || hasExpoPackage ? 'expo' : 'react-native'; +} + +function saveEditionConfig(projectRoot, edition) { + const config = { + edition: edition.toUpperCase(), + version: '3.2.1', + timestamp: new Date().toISOString(), + }; + + const configPath = path.join(projectRoot, 'cbl-edition.json'); + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); + + // Update .gitignore if it exists + const gitignorePath = path.join(projectRoot, '.gitignore'); + if (fs.existsSync(gitignorePath)) { + const gitignore = fs.readFileSync(gitignorePath, 'utf8'); + if (!gitignore.includes('cbl-edition.json')) { + fs.appendFileSync( + gitignorePath, + '\n# Couchbase Lite configuration\ncbl-edition.json\n' + ); + } + } +} + +function configureExpoProject(projectRoot, edition) { + console.log( + `\nšŸ“± Configuring Expo project for ${EDITIONS[edition].name} Edition...\n` + ); + + // Save the configuration file + saveEditionConfig(projectRoot, edition); + + // Check if already in app.json/app.config.js + const appJsonPath = path.join(projectRoot, 'app.json'); + const appConfigPath = path.join(projectRoot, 'app.config.js'); + + let configured = false; + + if (fs.existsSync(appJsonPath)) { + try { + const appJson = JSON.parse(fs.readFileSync(appJsonPath, 'utf8')); + if (!appJson.expo) appJson.expo = {}; + if (!appJson.expo.plugins) appJson.expo.plugins = []; + + // Check if plugin already exists + const hasPlugin = appJson.expo.plugins.some((p) => + Array.isArray(p) ? p[0] === 'cbl-reactnative' : p === 'cbl-reactnative' + ); + + if (!hasPlugin) { + appJson.expo.plugins.push('cbl-reactnative'); + fs.writeFileSync(appJsonPath, JSON.stringify(appJson, null, 2)); + configured = true; + } + } catch (error) { + console.error('Error updating app.json:', error.message); + } + } + + console.log('Configuration saved to cbl-edition.json'); + + if (!configured) { + console.log('\nšŸ“ Add this to your app.json or app.config.js:'); + console.log('\n "plugins": ["cbl-reactnative"]\n'); + } + + console.log('\nšŸ”„ Next steps:'); + console.log(' 1. Run: expo prebuild --clean'); + console.log(' 2. Run: expo run:ios or expo run:android\n'); + + if (edition === 'EE') { + console.log(' Enterprise Edition Notes:'); + console.log(' - Ensure you have a valid Couchbase Enterprise license'); + console.log( + ' - You may need to configure additional repository access\n' + ); + } +} + +function configureReactNativeProject(projectRoot, edition) { + console.log( + `\nšŸ“± Configuring React Native project for ${EDITIONS[edition].name} Edition...\n` + ); + + // Save the configuration file + saveEditionConfig(projectRoot, edition); + + const editionConfig = EDITIONS[edition]; + + console.log('Configuration saved to cbl-edition.json'); + console.log('\n Manual configuration required:\n'); + + console.log('ANDROID - Add to android/app/build.gradle:'); + console.log('```gradle'); + console.log('android {'); + console.log(' configurations.all {'); + console.log(' resolutionStrategy {'); + console.log(` force "${editionConfig.android}:3.2.1"`); + console.log(' }'); + console.log(' }'); + console.log('}'); + console.log('```\n'); + + console.log('iOS - Add to ios/Podfile:'); + if (edition === 'EE') { + console.log( + "source 'https://github.com/couchbase/couchbase-lite-ios-ee.git'" + ); + } + console.log('```ruby'); + console.log('target "YourApp" do'); + console.log( + ` pod '${editionConfig.ios}', '3.2.1', :modular_headers => true` + ); + console.log(' # ... rest of your pods'); + console.log('end'); + console.log('```\n'); + + console.log('Next steps:'); + console.log(' Android: cd android && ./gradlew clean && cd ..'); + console.log(' iOS: cd ios && pod install && cd ..\n'); +} + +function main() { + const args = process.argv.slice(2); + const edition = (args[0] || 'CE').toUpperCase(); + + if (!EDITIONS[edition]) { + console.error(` Invalid edition: ${edition}`); + console.error(' Usage: npx cbl-reactnative-configure [CE|EE]'); + process.exit(1); + } + + const projectRoot = findProjectRoot(); + const projectType = detectProjectType(projectRoot); + + console.log(`\n Couchbase Lite React Native Configuration`); + console.log(` Project type: ${projectType}`); + console.log(` Project root: ${projectRoot}`); + console.log(` Edition: ${EDITIONS[edition].name} (${edition})`); + + if (projectType === 'expo') { + configureExpoProject(projectRoot, edition); + } else { + configureReactNativeProject(projectRoot, edition); + } +} + +// Run if called directly +if (require.main === module) { + main(); +} + +module.exports = { EDITIONS, findProjectRoot, detectProjectType };