├── app.plugin.js ├── plugin ├── build │ ├── pluginConfig.js │ ├── index.d.ts │ ├── android │ │ ├── stringsDependency.d.ts │ │ ├── settingsDependency.d.ts │ │ ├── buildscriptDependency.d.ts │ │ ├── mainApplicationDependency.d.ts │ │ ├── index.d.ts │ │ ├── settingsDependency.js │ │ ├── index.js │ │ ├── stringsDependency.js │ │ ├── mainApplicationDependency.js │ │ └── buildscriptDependency.js │ ├── ios │ │ ├── appDelegateDependency.d.ts │ │ ├── buildscriptDependency.d.ts │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── buildscriptDependency.js │ │ └── appDelegateDependency.js │ ├── pluginConfig.d.ts │ └── index.js ├── src │ ├── ios │ │ ├── index.ts │ │ ├── buildscriptDependency.ts │ │ └── appDelegateDependency.ts │ ├── pluginConfig.ts │ ├── android │ │ ├── index.ts │ │ ├── settingsDependency.ts │ │ ├── stringsDependency.ts │ │ ├── mainApplicationDependency.ts │ │ └── buildscriptDependency.ts │ └── index.ts └── tsconfig.json └── README.md /app.plugin.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./plugin/build') 2 | -------------------------------------------------------------------------------- /plugin/build/pluginConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /plugin/build/index.d.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin } from 'expo/config-plugins'; 2 | import { PluginConfigType } from './pluginConfig'; 3 | declare const _default: ConfigPlugin; 4 | export default _default; 5 | -------------------------------------------------------------------------------- /plugin/build/android/stringsDependency.d.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin } from 'expo/config-plugins'; 2 | import { PluginConfigType } from '../pluginConfig'; 3 | export declare const withAndroidStringsDependency: ConfigPlugin; 4 | -------------------------------------------------------------------------------- /plugin/build/ios/appDelegateDependency.d.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin } from 'expo/config-plugins'; 2 | import { PluginConfigType } from '../pluginConfig'; 3 | export declare const withIosAppDelegateDependency: ConfigPlugin; 4 | -------------------------------------------------------------------------------- /plugin/build/ios/buildscriptDependency.d.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin } from 'expo/config-plugins'; 2 | import { PluginConfigType } from '../pluginConfig'; 3 | export declare const withIosBuildscriptDependency: ConfigPlugin; 4 | -------------------------------------------------------------------------------- /plugin/build/android/settingsDependency.d.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin } from 'expo/config-plugins'; 2 | import { PluginConfigType } from '../pluginConfig'; 3 | export declare const withAndroidSettingsDependency: ConfigPlugin; 4 | -------------------------------------------------------------------------------- /plugin/build/android/buildscriptDependency.d.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin } from 'expo/config-plugins'; 2 | import { PluginConfigType } from '../pluginConfig'; 3 | export declare const withAndroidBuildscriptDependency: ConfigPlugin; 4 | -------------------------------------------------------------------------------- /plugin/src/ios/index.ts: -------------------------------------------------------------------------------- 1 | import { withIosAppDelegateDependency } from './appDelegateDependency' 2 | import { withIosBuildscriptDependency } from './buildscriptDependency' 3 | 4 | export { withIosBuildscriptDependency, withIosAppDelegateDependency } 5 | -------------------------------------------------------------------------------- /plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo-module-scripts/tsconfig.plugin", 3 | "compilerOptions": { 4 | "outDir": "build", 5 | "rootDir": "src" 6 | }, 7 | "include": ["./src"], 8 | "exclude": ["**/__mocks__/*", "**/__tests__/*"] 9 | } -------------------------------------------------------------------------------- /plugin/build/android/mainApplicationDependency.d.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin } from 'expo/config-plugins'; 2 | import { PluginConfigType } from '../pluginConfig'; 3 | export declare const withAndroidMainApplicationDependency: ConfigPlugin; 4 | -------------------------------------------------------------------------------- /plugin/build/ios/index.d.ts: -------------------------------------------------------------------------------- 1 | import { withIosAppDelegateDependency } from './appDelegateDependency'; 2 | import { withIosBuildscriptDependency } from './buildscriptDependency'; 3 | export { withIosBuildscriptDependency, withIosAppDelegateDependency }; 4 | -------------------------------------------------------------------------------- /plugin/src/pluginConfig.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Configuration for `react-native-code-push` 3 | */ 4 | export interface PluginConfigType { 5 | ios: { 6 | CodePushDeploymentKey: string 7 | } 8 | android: { 9 | CodePushDeploymentKey: string 10 | CodePushPublicKey?: string 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /plugin/build/pluginConfig.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Configuration for `react-native-code-push` 3 | */ 4 | export interface PluginConfigType { 5 | ios: { 6 | CodePushDeploymentKey: string; 7 | }; 8 | android: { 9 | CodePushDeploymentKey: string; 10 | CodePushPublicKey?: string; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /plugin/build/android/index.d.ts: -------------------------------------------------------------------------------- 1 | import { withAndroidBuildscriptDependency } from './buildscriptDependency'; 2 | import { withAndroidMainApplicationDependency } from './mainApplicationDependency'; 3 | import { withAndroidSettingsDependency } from './settingsDependency'; 4 | import { withAndroidStringsDependency } from './stringsDependency'; 5 | export { withAndroidBuildscriptDependency, withAndroidSettingsDependency, withAndroidStringsDependency, withAndroidMainApplicationDependency, }; 6 | -------------------------------------------------------------------------------- /plugin/src/android/index.ts: -------------------------------------------------------------------------------- 1 | import { withAndroidBuildscriptDependency } from './buildscriptDependency' 2 | import { withAndroidMainApplicationDependency } from './mainApplicationDependency' 3 | import { withAndroidSettingsDependency } from './settingsDependency' 4 | import { withAndroidStringsDependency } from './stringsDependency' 5 | 6 | export { 7 | withAndroidBuildscriptDependency, 8 | withAndroidSettingsDependency, 9 | withAndroidStringsDependency, 10 | withAndroidMainApplicationDependency, 11 | } 12 | -------------------------------------------------------------------------------- /plugin/src/ios/buildscriptDependency.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin, withInfoPlist } from 'expo/config-plugins' 2 | 3 | import { PluginConfigType } from '../pluginConfig' 4 | 5 | // Pass `` to specify that this plugin requires a string property. 6 | export const withIosBuildscriptDependency: ConfigPlugin = (config, props) => { 7 | if (!props.ios.CodePushDeploymentKey) return config 8 | return withInfoPlist(config, (config) => { 9 | config.modResults.CodePushDeploymentKey = props.ios.CodePushDeploymentKey 10 | return config 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /plugin/build/ios/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.withIosAppDelegateDependency = exports.withIosBuildscriptDependency = void 0; 4 | const appDelegateDependency_1 = require("./appDelegateDependency"); 5 | Object.defineProperty(exports, "withIosAppDelegateDependency", { enumerable: true, get: function () { return appDelegateDependency_1.withIosAppDelegateDependency; } }); 6 | const buildscriptDependency_1 = require("./buildscriptDependency"); 7 | Object.defineProperty(exports, "withIosBuildscriptDependency", { enumerable: true, get: function () { return buildscriptDependency_1.withIosBuildscriptDependency; } }); 8 | -------------------------------------------------------------------------------- /plugin/build/ios/buildscriptDependency.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.withIosBuildscriptDependency = void 0; 4 | const config_plugins_1 = require("expo/config-plugins"); 5 | // Pass `` to specify that this plugin requires a string property. 6 | const withIosBuildscriptDependency = (config, props) => { 7 | if (!props.ios.CodePushDeploymentKey) 8 | return config; 9 | return (0, config_plugins_1.withInfoPlist)(config, (config) => { 10 | config.modResults.CodePushDeploymentKey = props.ios.CodePushDeploymentKey; 11 | return config; 12 | }); 13 | }; 14 | exports.withIosBuildscriptDependency = withIosBuildscriptDependency; 15 | -------------------------------------------------------------------------------- /plugin/src/android/settingsDependency.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin, withSettingsGradle } from 'expo/config-plugins' 2 | 3 | import { PluginConfigType } from '../pluginConfig' 4 | 5 | /** 6 | * Update `/settings.gradle` by adding react-native-code-push 7 | */ 8 | 9 | function applySettings(gradleSettings: string) { 10 | const codePushSettings = `\ninclude ':react-native-code-push'\nproject(':react-native-code-push').projectDir = new File(["node", "--print", "require.resolve('react-native-code-push/package.json')"].execute(null, rootDir).text.trim(), "../android/app")` 11 | 12 | // Make sure the project does not have the settings already 13 | if (!gradleSettings.includes(`include ':react-native-code-push'`)) { 14 | return gradleSettings + codePushSettings 15 | } 16 | 17 | return gradleSettings 18 | } 19 | 20 | export const withAndroidSettingsDependency: ConfigPlugin = (config) => { 21 | return withSettingsGradle(config, (config) => { 22 | config.modResults.contents = applySettings(config.modResults.contents) 23 | return config 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /plugin/src/ios/appDelegateDependency.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin, withAppDelegate } from 'expo/config-plugins' 2 | 3 | import { PluginConfigType } from '../pluginConfig' 4 | 5 | function applyImplementation(appDelegate: string, find: string, add: string, replace?: boolean) { 6 | // Make sure the project does not have the settings already 7 | if (!appDelegate.includes(add)) { 8 | if (replace) return appDelegate.replace(find, add) 9 | else return appDelegate.replace(find, `${find}\n${add}`) 10 | } 11 | 12 | return appDelegate 13 | } 14 | 15 | export const withIosAppDelegateDependency: ConfigPlugin = (config, props) => { 16 | return withAppDelegate(config, (config) => { 17 | config.modResults.contents = applyImplementation( 18 | config.modResults.contents, 19 | `#import "AppDelegate.h"`, 20 | `#import ` 21 | ) 22 | config.modResults.contents = applyImplementation( 23 | config.modResults.contents, 24 | `return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];`, 25 | `return [CodePush bundleURL];`, 26 | true 27 | ) 28 | return config 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /plugin/build/android/settingsDependency.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.withAndroidSettingsDependency = void 0; 4 | const config_plugins_1 = require("expo/config-plugins"); 5 | /** 6 | * Update `/settings.gradle` by adding react-native-code-push 7 | */ 8 | function applySettings(gradleSettings) { 9 | const codePushSettings = `\ninclude ':react-native-code-push'\nproject(':react-native-code-push').projectDir = new File(["node", "--print", "require.resolve('react-native-code-push/package.json')"].execute(null, rootDir).text.trim(), "../android/app")`; 10 | // Make sure the project does not have the settings already 11 | if (!gradleSettings.includes(`include ':react-native-code-push'`)) { 12 | return gradleSettings + codePushSettings; 13 | } 14 | return gradleSettings; 15 | } 16 | const withAndroidSettingsDependency = (config) => { 17 | return (0, config_plugins_1.withSettingsGradle)(config, (config) => { 18 | config.modResults.contents = applySettings(config.modResults.contents); 19 | return config; 20 | }); 21 | }; 22 | exports.withAndroidSettingsDependency = withAndroidSettingsDependency; 23 | -------------------------------------------------------------------------------- /plugin/build/ios/appDelegateDependency.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.withIosAppDelegateDependency = void 0; 4 | const config_plugins_1 = require("expo/config-plugins"); 5 | function applyImplementation(appDelegate, find, add, replace) { 6 | // Make sure the project does not have the settings already 7 | if (!appDelegate.includes(add)) { 8 | if (replace) 9 | return appDelegate.replace(find, add); 10 | else 11 | return appDelegate.replace(find, `${find}\n${add}`); 12 | } 13 | return appDelegate; 14 | } 15 | const withIosAppDelegateDependency = (config, props) => { 16 | return (0, config_plugins_1.withAppDelegate)(config, (config) => { 17 | config.modResults.contents = applyImplementation(config.modResults.contents, `#import "AppDelegate.h"`, `#import `); 18 | config.modResults.contents = applyImplementation(config.modResults.contents, `return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];`, `return [CodePush bundleURL];`, true); 19 | return config; 20 | }); 21 | }; 22 | exports.withIosAppDelegateDependency = withIosAppDelegateDependency; 23 | -------------------------------------------------------------------------------- /plugin/src/android/stringsDependency.ts: -------------------------------------------------------------------------------- 1 | import { AndroidConfig, ConfigPlugin, withStringsXml } from 'expo/config-plugins' 2 | import { ResourceXML } from '@expo/config-plugins/build/android/Resources' 3 | 4 | import { PluginConfigType } from '../pluginConfig' 5 | 6 | /** 7 | * Update `/app/src/main/res/values/strings.xml` by adding react-native-code-push deployment key 8 | */ 9 | 10 | function setStrings(strings: ResourceXML, name: string, value: string) { 11 | // Helper to add string.xml JSON items or overwrite existing items with the same name. 12 | return AndroidConfig.Strings.setStringItem( 13 | [ 14 | // XML represented as JSON 15 | // value 16 | { $: { name }, _: value }, 17 | ], 18 | strings 19 | ) 20 | } 21 | 22 | export const withAndroidStringsDependency: ConfigPlugin = (config, props) => { 23 | return withStringsXml(config, (config) => { 24 | config.modResults = setStrings(config.modResults, 'CodePushDeploymentKey', props.android.CodePushDeploymentKey) 25 | if (props.android.CodePushPublicKey) config.modResults = setStrings(config.modResults, 'CodePushPublicKey', props.android.CodePushPublicKey) 26 | return config 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /plugin/build/android/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.withAndroidMainApplicationDependency = exports.withAndroidStringsDependency = exports.withAndroidSettingsDependency = exports.withAndroidBuildscriptDependency = void 0; 4 | const buildscriptDependency_1 = require("./buildscriptDependency"); 5 | Object.defineProperty(exports, "withAndroidBuildscriptDependency", { enumerable: true, get: function () { return buildscriptDependency_1.withAndroidBuildscriptDependency; } }); 6 | const mainApplicationDependency_1 = require("./mainApplicationDependency"); 7 | Object.defineProperty(exports, "withAndroidMainApplicationDependency", { enumerable: true, get: function () { return mainApplicationDependency_1.withAndroidMainApplicationDependency; } }); 8 | const settingsDependency_1 = require("./settingsDependency"); 9 | Object.defineProperty(exports, "withAndroidSettingsDependency", { enumerable: true, get: function () { return settingsDependency_1.withAndroidSettingsDependency; } }); 10 | const stringsDependency_1 = require("./stringsDependency"); 11 | Object.defineProperty(exports, "withAndroidStringsDependency", { enumerable: true, get: function () { return stringsDependency_1.withAndroidStringsDependency; } }); 12 | -------------------------------------------------------------------------------- /plugin/build/android/stringsDependency.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.withAndroidStringsDependency = void 0; 4 | const config_plugins_1 = require("expo/config-plugins"); 5 | /** 6 | * Update `/app/src/main/res/values/strings.xml` by adding react-native-code-push deployment key 7 | */ 8 | function setStrings(strings, name, value) { 9 | // Helper to add string.xml JSON items or overwrite existing items with the same name. 10 | return config_plugins_1.AndroidConfig.Strings.setStringItem([ 11 | // XML represented as JSON 12 | // value 13 | { $: { name }, _: value }, 14 | ], strings); 15 | } 16 | const withAndroidStringsDependency = (config, props) => { 17 | return (0, config_plugins_1.withStringsXml)(config, (config) => { 18 | config.modResults = setStrings(config.modResults, 'CodePushDeploymentKey', props.android.CodePushDeploymentKey); 19 | if (props.android.CodePushPublicKey) 20 | config.modResults = setStrings(config.modResults, 'CodePushPublicKey', props.android.CodePushPublicKey); 21 | return config; 22 | }); 23 | }; 24 | exports.withAndroidStringsDependency = withAndroidStringsDependency; 25 | -------------------------------------------------------------------------------- /plugin/build/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const config_plugins_1 = require("expo/config-plugins"); 4 | const android_1 = require("./android"); 5 | const ios_1 = require("./ios"); 6 | /** 7 | * A config plugin for configuring `react-native-code-push` 8 | */ 9 | const withRnCodepush = (config, props) => { 10 | config = (0, android_1.withAndroidBuildscriptDependency)(config, props); 11 | config = (0, android_1.withAndroidSettingsDependency)(config, props); 12 | config = (0, android_1.withAndroidStringsDependency)(config, props); 13 | config = (0, android_1.withAndroidMainApplicationDependency)(config, props); 14 | // plugins order matter: the later one would run first 15 | config = (0, ios_1.withIosBuildscriptDependency)(config, props); 16 | config = (0, ios_1.withIosAppDelegateDependency)(config, props); 17 | return config; 18 | }; 19 | // @todo: Is it needed to declare this var? as it's rewritten at #34 20 | let pkg = { 21 | name: "react-native-code-push", 22 | // UNVERSIONED... 23 | }; 24 | try { 25 | const codePushPkg = require("react-native-code-push/package.json"); 26 | pkg = codePushPkg; 27 | } 28 | catch { } 29 | exports.default = (0, config_plugins_1.createRunOncePlugin)(withRnCodepush, pkg.name, pkg.version); 30 | -------------------------------------------------------------------------------- /plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | import {ConfigPlugin, createRunOncePlugin} from 'expo/config-plugins' 2 | 3 | import { 4 | withAndroidBuildscriptDependency, 5 | withAndroidMainApplicationDependency, 6 | withAndroidSettingsDependency, 7 | withAndroidStringsDependency, 8 | } from './android' 9 | import {withIosAppDelegateDependency, withIosBuildscriptDependency} from './ios' 10 | import {PluginConfigType} from './pluginConfig' 11 | 12 | /** 13 | * A config plugin for configuring `react-native-code-push` 14 | */ 15 | const withRnCodepush: ConfigPlugin = (config, props) => { 16 | config = withAndroidBuildscriptDependency(config, props) 17 | config = withAndroidSettingsDependency(config, props) 18 | config = withAndroidStringsDependency(config, props) 19 | config = withAndroidMainApplicationDependency(config, props) 20 | // plugins order matter: the later one would run first 21 | config = withIosBuildscriptDependency(config, props) 22 | config = withIosAppDelegateDependency(config, props) 23 | 24 | return config 25 | } 26 | 27 | // @todo: Is it needed to declare this var? as it's rewritten at #34 28 | let pkg: { name: string; version?: string } = { 29 | name: "react-native-code-push", 30 | // UNVERSIONED... 31 | }; 32 | try { 33 | const codePushPkg = require("react-native-code-push/package.json"); 34 | pkg = codePushPkg; 35 | } catch {} 36 | export default createRunOncePlugin(withRnCodepush, pkg.name, pkg.version); 37 | -------------------------------------------------------------------------------- /plugin/build/android/mainApplicationDependency.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.withAndroidMainApplicationDependency = void 0; 4 | const config_plugins_1 = require("expo/config-plugins"); 5 | /** 6 | * Update `/build.gradle` by adding the codepush.gradle file 7 | * as an additional build task definition underneath react.gradle 8 | */ 9 | function applyImplementation(mainApplication, find, add, replace) { 10 | // Make sure the project does not have the settings already 11 | if (!mainApplication.includes(add)) { 12 | if (replace) 13 | return mainApplication.replace(find, add); 14 | else 15 | return mainApplication.replace(find, `${find}\n${add}`); 16 | } 17 | return mainApplication; 18 | } 19 | const withAndroidMainApplicationDependency = (config) => { 20 | return (0, config_plugins_1.withMainApplication)(config, (config) => { 21 | config.modResults.contents = applyImplementation(config.modResults.contents, 'import expo.modules.ReactNativeHostWrapper;', `\nimport com.microsoft.codepush.react.CodePush;`); 22 | if (config.modResults.contents.includes("new DefaultReactNativeHost(this) {")) { 23 | config.modResults.contents = applyImplementation(config.modResults.contents, `new DefaultReactNativeHost(this) {`, ` 24 | @Override 25 | protected String getJSBundleFile() { 26 | return CodePush.getJSBundleFile(); 27 | }\n`); 28 | } 29 | else if (config.modResults.contents.includes(" new ReactNativeHost(this) {")) { 30 | config.modResults.contents = applyImplementation(config.modResults.contents, `new ReactNativeHost(this) {`, ` 31 | @Override 32 | protected String getJSBundleFile() { 33 | return CodePush.getJSBundleFile(); 34 | }\n`); 35 | } 36 | return config; 37 | }); 38 | }; 39 | exports.withAndroidMainApplicationDependency = withAndroidMainApplicationDependency; 40 | -------------------------------------------------------------------------------- /plugin/src/android/mainApplicationDependency.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin, withMainApplication } from 'expo/config-plugins' 2 | 3 | import { PluginConfigType } from '../pluginConfig' 4 | 5 | /** 6 | * Update `/build.gradle` by adding the codepush.gradle file 7 | * as an additional build task definition underneath react.gradle 8 | */ 9 | 10 | function applyImplementation( 11 | mainApplication: string, 12 | find: string, 13 | add: string, 14 | replace?: boolean 15 | ) { 16 | // Make sure the project does not have the settings already 17 | if (!mainApplication.includes(add)) { 18 | if (replace) return mainApplication.replace(find, add) 19 | else return mainApplication.replace(find, `${find}\n${add}`) 20 | } 21 | 22 | return mainApplication 23 | } 24 | 25 | export const withAndroidMainApplicationDependency: ConfigPlugin = (config) => { 26 | return withMainApplication(config, (config) => { 27 | config.modResults.contents = applyImplementation( 28 | config.modResults.contents, 29 | 'import expo.modules.ReactNativeHostWrapper;', 30 | `\nimport com.microsoft.codepush.react.CodePush;` 31 | ) 32 | if ( 33 | config.modResults.contents.includes("new DefaultReactNativeHost(this) {") 34 | ) { 35 | config.modResults.contents = applyImplementation( 36 | config.modResults.contents, 37 | `new DefaultReactNativeHost(this) {`, 38 | ` 39 | @Override 40 | protected String getJSBundleFile() { 41 | return CodePush.getJSBundleFile(); 42 | }\n` 43 | ); 44 | } else if ( 45 | config.modResults.contents.includes(" new ReactNativeHost(this) {") 46 | ) { 47 | config.modResults.contents = applyImplementation( 48 | config.modResults.contents, 49 | `new ReactNativeHost(this) {`, 50 | ` 51 | @Override 52 | protected String getJSBundleFile() { 53 | return CodePush.getJSBundleFile(); 54 | }\n` 55 | ); 56 | } 57 | return config; 58 | }) 59 | } 60 | -------------------------------------------------------------------------------- /plugin/src/android/buildscriptDependency.ts: -------------------------------------------------------------------------------- 1 | import { ConfigPlugin, withAppBuildGradle } from 'expo/config-plugins' 2 | 3 | import { PluginConfigType } from '../pluginConfig' 4 | 5 | /** 6 | * Update `/build.gradle` by adding the codepush.gradle file 7 | * as an additional build task definition underneath react.gradle 8 | */ 9 | 10 | function applyImplementation(appBuildGradle: string) { 11 | const codePushImplementation = `apply from: new File(["node", "--print", "require.resolve('react-native-code-push/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/android/codepush.gradle"`; 12 | 13 | // Make sure the project does not have the dependency already 14 | if (!appBuildGradle.includes(codePushImplementation)) { 15 | const reactNativeFileClassGradleInclude = `'apply from: new File(reactNativeRoot, "react.gradle")`; 16 | if (appBuildGradle.includes(reactNativeFileClassGradleInclude)) { 17 | return appBuildGradle.replace( 18 | reactNativeFileClassGradleInclude, 19 | `${reactNativeFileClassGradleInclude}\n${codePushImplementation}` 20 | ); 21 | } 22 | const reactNativeRawGradleInclude = `apply from: "../../node_modules/react-native/react.gradle"`; 23 | if (appBuildGradle.includes(reactNativeRawGradleInclude)) { 24 | return appBuildGradle.replace( 25 | reactNativeRawGradleInclude, 26 | `${reactNativeRawGradleInclude}\n${codePushImplementation}` 27 | ); 28 | } 29 | const reactNative71Include = `apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle");`; 30 | if (appBuildGradle.includes(reactNative71Include)) { 31 | return appBuildGradle.replace( 32 | reactNative71Include, 33 | `${reactNative71Include}\n${codePushImplementation}` 34 | ); 35 | } 36 | } 37 | return appBuildGradle; 38 | } 39 | export const withAndroidBuildscriptDependency: ConfigPlugin = (config) => { 40 | return withAppBuildGradle(config, (config) => { 41 | config.modResults.contents = applyImplementation(config.modResults.contents) 42 | return config 43 | }) 44 | } 45 | -------------------------------------------------------------------------------- /plugin/build/android/buildscriptDependency.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.withAndroidBuildscriptDependency = void 0; 4 | const config_plugins_1 = require("expo/config-plugins"); 5 | /** 6 | * Update `/build.gradle` by adding the codepush.gradle file 7 | * as an additional build task definition underneath react.gradle 8 | */ 9 | function applyImplementation(appBuildGradle) { 10 | const codePushImplementation = `apply from: new File(["node", "--print", "require.resolve('react-native-code-push/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/android/codepush.gradle"`; 11 | // Make sure the project does not have the dependency already 12 | if (!appBuildGradle.includes(codePushImplementation)) { 13 | const reactNativeFileClassGradleInclude = `'apply from: new File(reactNativeRoot, "react.gradle")`; 14 | if (appBuildGradle.includes(reactNativeFileClassGradleInclude)) { 15 | return appBuildGradle.replace(reactNativeFileClassGradleInclude, `${reactNativeFileClassGradleInclude}\n${codePushImplementation}`); 16 | } 17 | const reactNativeRawGradleInclude = `apply from: "../../node_modules/react-native/react.gradle"`; 18 | if (appBuildGradle.includes(reactNativeRawGradleInclude)) { 19 | return appBuildGradle.replace(reactNativeRawGradleInclude, `${reactNativeRawGradleInclude}\n${codePushImplementation}`); 20 | } 21 | const reactNative71Include = `apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle");`; 22 | if (appBuildGradle.includes(reactNative71Include)) { 23 | return appBuildGradle.replace(reactNative71Include, `${reactNative71Include}\n${codePushImplementation}`); 24 | } 25 | } 26 | return appBuildGradle; 27 | } 28 | const withAndroidBuildscriptDependency = (config) => { 29 | return (0, config_plugins_1.withAppBuildGradle)(config, (config) => { 30 | config.modResults.contents = applyImplementation(config.modResults.contents); 31 | return config; 32 | }); 33 | }; 34 | exports.withAndroidBuildscriptDependency = withAndroidBuildscriptDependency; 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | refactor this documentation adding some emojis and adjust some english mistakes: 2 | 3 | # react-native-code-push-expo-plugin 4 | A plug-in for using react-native-code-push with Expo managed/bare workflow 5 | 6 | ## Setup 7 | 8 | 1. Copy the files from this repo and place them into your Expo app directory. 9 | 2. Install the appcenter-cli: 10 | ```ssh 11 | npm install -g appcenter-cli 12 | ``` 13 | 3. Install codepush library: 14 | ```ssh 15 | npm install react-native-code-push 16 | ``` 17 | 4. Create an *app.plugin.js* file and add the following code: 18 | ```javascript 19 | module.exports = require("./plugin/build"); 20 | ``` 21 | 3. Add the following to your Expo app config 22 | 4. Adjust the plugin files as needed for your use case. This will not be a plug-and-play situation in most cases. 23 | 24 | ### Plugin Installation for Expo (Android) 25 | 26 | 1. Open your Expo app config file (*app.json*). 27 | 28 | 2. Insert the following into the plugins section of your config (Don't duplicate configuration, if the './app.plugin' item already exists, simply add the android portion.). Create the plugins section if it doesn't already exist. 29 | 30 | ```javascript 31 | "plugins":[ 32 | [ 33 | "./app.plugin", 34 | { 35 | "android": { 36 | "CodePushDeploymentKey": "YOUR_ANDROID_CODE_PUSH_KEY", 37 | } 38 | } 39 | ] 40 | ] 41 | ``` 42 | 43 | 3. Replace `YOUR_ANDROID_CODE_PUSH_KEY` with the Deployment key. 44 | 4. To release a signed release replace your CodePushPublicKey with a public key (https://github.com/microsoft/code-push/tree/v3.0.1/cli#code-signing): 45 | 46 | ```javascript 47 | "plugins":[ 48 | [ 49 | "./app.plugin", 50 | { 51 | "android": { 52 | "CodePushDeploymentKey": "YOUR_ANDROID_CODE_PUSH_KEY", 53 | "CodePushPublicKey": "-----BEGIN PUBLIC KEY-----\nYOUR_PUBLIC_KEY\n-----END PUBLIC KEY-----" 54 | } 55 | } 56 | ] 57 | ] 58 | ``` 59 | 60 | 5. Run `npx expo prebuild` to regenerate your native code with the codepush dependencies. 61 | 6. To generate an update use the following code: 62 | ```ssh 63 | appcenter codepush release-react -a /MyApp -d Production -k private.pem 64 | ``` 65 | 66 | ### Plugin Installation for Expo (IOS) 67 | 68 | React Native Code Push comes packaged with a plugin to automate some of the setup process: 69 | 70 | 1. Open your Expo app config file (app.config.json or app.config.js instead of app.json). 71 | 72 | 2. Insert the following into the plugins section of your config (Don't duplicate configuration, if the './app.plugin' item already exists, simply add the ios portion.). Create the plugins section if it doesn't already exist. 73 | 74 | ```javascript 75 | "plugins": [ 76 | [ 77 | './app.plugin', 78 | { 79 | ios: { 80 | CodePushDeploymentKey: 'YOUR_IOS_CODE_PUSH_KEY', 81 | }, 82 | } 83 | ] 84 | ] 85 | ``` 86 | 87 | 3. Replace `YOUR_IOS_CODE_PUSH_KEY` with the Deployment key. 88 | 89 | 4. Run `npx expo prebuild` to regenerate your native code with the codepush dependencies. 90 | 5. To generate an update use the following code: 91 | ```ssh 92 | appcenter codepush release-react -a /MyApp -d Production -k private.pem 93 | ``` 94 | --------------------------------------------------------------------------------