Skip to content

Instantly share code, notes, and snippets.

@grossadamm
Created January 4, 2023 23:15
Show Gist options
  • Save grossadamm/b68a7d1f70d4884ecc760bc73107497b to your computer and use it in GitHub Desktop.
Save grossadamm/b68a7d1f70d4884ecc760bc73107497b to your computer and use it in GitHub Desktop.
Use code push with expo
const { AndroidConfig, withAppDelegate, withPlugins, withInfoPlist, withSettingsGradle, withAppBuildGradle, withMainApplication, withStringsXml } = require('@expo/config-plugins');
function withCodePushAppDelegate(config) {
return withAppDelegate(config, (cfg) => {
const { modResults } = cfg;
const { contents } = modResults;
const lines = contents.split('\n');
const importIndex = lines.findIndex((line) =>
/^#import "AppDelegate.h"/.test(line)
);
const bundleURLIndex = lines.findIndex((line) =>
line.includes('return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];')
);
modResults.contents = [
...lines.slice(0, importIndex + 1),
'#import <CodePush/CodePush.h>',
// ...lines.slice(importIndex + 1)
...lines.slice(importIndex + 1, bundleURLIndex),
' return [CodePush bundleURL];',
...lines.slice(bundleURLIndex + 1),
].join('\n');
return cfg;
});
}
function applySettings(gradleSettings: string) {
const settings = `include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')`
// Make sure the project does not have the settings already
if (!gradleSettings.includes(`include ':react-native-code-push'`)) {
return gradleSettings + settings
}
return gradleSettings
}
function withCodePushSettingsGradle(config) {
return withSettingsGradle(config, (cfg) => {
cfg.modResults.contents = applySettings(cfg.modResults.contents)
return cfg
})
}
function addApplies(appBuildGradle: string) {
const applies = `apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"`
// Make sure the project does not have the dependency already
if (!appBuildGradle.includes(applies)) {
return appBuildGradle.replace(
/apply from: new File(reactNativeRoot, "react.gradle")/,
`apply from: new File(reactNativeRoot, "react.gradle")
${applies}`
)
}
return appBuildGradle
}
function withCodePushBuildGradle(config) {
return withAppBuildGradle(config, (cfg) => {
cfg.modResults.contents = addApplies(cfg.modResults.contents)
return cfg
})
}
function applyMainApplication(mainApplication: string) {
const packageImport = `import com.microsoft.codepush.react.CodePush;\n`
const jsBundle = `protected String getJSBundleFile() {
return CodePush.getJSBundleFile();
}`
// Make sure the project does not have the settings already
if (!mainApplication.includes(packageImport)) {
mainApplication = mainApplication.replace(
/import android.app.Application;/,
`import android.app.Application;\n${packageImport}`
)
}
if (!mainApplication.includes("getJSBundleFile")) {
mainApplication = mainApplication.replace(
/protected String getJSMainModuleName\(\) {/,
`${jsBundle}
@Override
protected String getJSMainModuleName() {`
)
}
return mainApplication
}
function withCodePushMainApplication(config) {
return withMainApplication(config, (cfg) => {
cfg.modResults.contents = applyMainApplication(cfg.modResults.contents)
return cfg
})
}
function withCodePushInfoPlist(config) {
return withInfoPlist(config, (cfg) => {
const { extra: { codePush: { production: { iosDeploymentKey }, codePushPublicKey } } } = cfg;
cfg.modResults.CodePushDeploymentKey = iosDeploymentKey;
cfg.modResults.CodePushPublicKey = codePushPublicKey;
return cfg;
});
}
function withCodePushStringsXml(config) {
return withStringsXml(config, (cfg) => {
const { extra: { codePush: { production: { androidDeploymentKey }, codePushPublicKey } } } = cfg;
cfg.modResults = AndroidConfig.Strings.setStringItem(
[
// XML represented as JSON
// <string name="CodePushDeploymentKey" moduleConfig="true">value</string>
{ $: { name: 'CodePushDeploymentKey', moduleConfig: 'true' }, _: androidDeploymentKey },
],
cfg.modResults
);
cfg.modResults = AndroidConfig.Strings.setStringItem(
[
// XML represented as JSON
// <string name="CodePushDeploymentKey">value</string>
{ $: { name: 'CodePushPublicKey' }, _: codePushPublicKey },
],
cfg.modResults
);
return cfg;
});
}
function withCodePush(config) {
return withPlugins(config, [
withCodePushAppDelegate,
withCodePushInfoPlist,
withCodePushSettingsGradle,
withCodePushBuildGradle,
withCodePushMainApplication,
withCodePushStringsXml
]);
}
export default withCodePush;
// {
// "expo": {
// "extra": {
// "codePush": {
// "production": {
// "iosDeploymentKey": "iosDeploymentKey",
// "androidDeploymentKey": "androidDeploymentKey"
// },
// "codePushPublicKey": "codePushPublicKey"
// }
// }
// }
//
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment