Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

expo-dev-launcher

Package Overview
Dependencies
Maintainers
24
Versions
187
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

expo-dev-launcher - npm Package Compare versions

Comparing version 0.7.0 to 0.8.0

android/src/testDebug/java/expo/modules/devlauncher/DevLauncherControllerTest.kt

7

build/DevLauncherErrorManager.js
let isErrorHandlingEnabled = true;
let wasHit = false; // whether the original error handler was called
const unavailableErrorPossibleSolutions = `Some possible solutions:

@@ -35,4 +36,10 @@ - Make sure that the method is available on the current platform.

if (error instanceof Error) {
// Suppresses `"main" has not been registered` error only if it was caused by a different error.
// Otherwise, we want to show it, cause the user may forget to call `AppRegistry.registerComponent`.
if (wasHit && error.message?.includes('has not been registered. This can happen if')) {
return;
}
customizeError(error);
}
wasHit = true;
originalHandler(error, isFatal);

@@ -39,0 +46,0 @@ }

@@ -13,2 +13,38 @@ # Changelog

## 0.8.0 — 2021-10-07
### 🛠 Breaking changes
- Added a native dependency on the `expo-manifests` package. ([#14461](https://github.com/expo/expo/pull/14461) by [@esamelson](https://github.com/esamelson))
- This is a breaking change for projects **without `react-native-unimodules` or `expo-modules-core` installed**. In order to upgrade from `expo-dev-client@0.5.1` or below to this version in such projects, the following changes must be made:
- In `ios/Podfile`, change the deployment target to `platform :ios, '12.0'` and add the following lines inside the main target:
```ruby
pod 'EXJSONUtils', path: '../node_modules/expo-json-utils/ios', :configurations => :debug
pod 'EXManifests', path: '../node_modules/expo-manifests/ios', :configurations => :debug
```
- In `android/settings.gradle`, add the following lines:
```groovy
include ':expo-json-utils'
project(':expo-json-utils').projectDir = new File('../node_modules/expo-json-utils/android')
```
include ':expo-manifests'
project(':expo-manifests').projectDir = new File('../node_modules/expo-manifests/android')
```
- No additional setup is necessary for projects already using `react-native-unimodules` or `expo-modules-core`.
- Replace Android DevLauncherManifest class with `expo-manifests`. ([#14462](https://github.com/expo/expo/pull/14462) by [@esamelson](https://github.com/esamelson))
- Replace iOS EXDevLauncherManifest class with `expo-manifests`. ([#14463](https://github.com/expo/expo/pull/14463) by [@esamelson](https://github.com/esamelson))
### 🎉 New features
- Suppress the `"main" has not been registered` exception if it was caused by a different error. ([#14363](https://github.com/expo/expo/pull/14363) by [@lukmccall](https://github.com/lukmccall))
- Added support for SDK 43. ([#14633](https://github.com/expo/expo/pull/14633) & [#14635](https://github.com/expo/expo/pull/14635) by [@lukmccall](https://github.com/lukmccall))
### 🐛 Bug fixes
- Fix intent that started activity isn't passed further. ([#14097](https://github.com/expo/expo/pull/14097) by [@lukmccall](https://github.com/lukmccall))
- Fix building errors from use_frameworks! in Podfile. ([#14523](https://github.com/expo/expo/pull/14523) by [@kudo](https://github.com/kudo))
### 💡 Others
- Updated `@expo/config-plugins` ([#14443](https://github.com/expo/expo/pull/14443) by [@EvanBacon](https://github.com/EvanBacon))
## 0.7.0 — 2021-09-02

@@ -15,0 +51,0 @@

12

package.json
{
"name": "expo-dev-launcher",
"title": "Expo Development Launcher",
"version": "0.7.0",
"version": "0.8.0",
"description": "Pre-release version of the Expo development launcher package for testing.",

@@ -31,3 +31,3 @@ "main": "build/DevLauncher.js",

"dependencies": {
"@expo/config-plugins": "^3.0.0",
"@expo/config-plugins": "^3.1.0",
"resolve-from": "^5.0.0",

@@ -37,8 +37,8 @@ "semver": "^7.3.5"

"devDependencies": {
"babel-preset-expo": "~8.4.1",
"babel-preset-expo": "~8.5.1",
"expo-module-scripts": "^2.0.0",
"react": "16.13.1",
"react-native": "0.63.2"
"react": "17.0.1",
"react-native": "0.64.2"
},
"gitHead": "6231eededd3121ab5448e6e303214ab7dc39de46"
"gitHead": "31266447e8372224432ce72db8a6e52aa7c5befa"
}

@@ -10,3 +10,5 @@ "use strict";

const semver_1 = __importDefault(require("semver"));
const constants_1 = require("./constants");
const resolveExpoUpdatesVersion_1 = require("./resolveExpoUpdatesVersion");
const utils_1 = require("./utils");
const withDevLauncherAppDelegate_1 = require("./withDevLauncherAppDelegate");

@@ -39,24 +41,5 @@ const pkg = require('expo-dev-launcher/package.json');

}
function addLines(content, find, offset, toAdd) {
const lines = content.split('\n');
let lineIndex = lines.findIndex(line => line.match(find));
for (const newLine of toAdd) {
if (!content.includes(newLine)) {
lines.splice(lineIndex + offset, 0, newLine);
lineIndex++;
}
}
return lines.join('\n');
}
function replaceLine(content, find, replace) {
const lines = content.split('\n');
if (!content.includes(replace)) {
const lineIndex = lines.findIndex(line => line.match(find));
lines.splice(lineIndex, 1, replace);
}
return lines.join('\n');
}
function addJavaImports(javaSource, javaImports) {
const lines = javaSource.split('\n');
const lineIndexWithPackageDeclaration = lines.findIndex(line => line.match(/^package .*;$/));
const lineIndexWithPackageDeclaration = lines.findIndex((line) => line.match(/^package .*;$/));
for (const javaImport of javaImports) {

@@ -77,3 +60,4 @@ if (!javaSource.includes(javaImport)) {

catch (e) {
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify MainApplication.java - ${e}.`);
config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Couldn't modify MainApplication.java - ${e}.
See the expo-dev-client installation instructions to modify your MainApplication.java manually: ${constants_1.InstallationPage}`);
}

@@ -88,3 +72,4 @@ }

catch (e) {
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify AppDelegate.m - ${e}.`);
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify AppDelegate.m - ${e}.
See the expo-dev-client installation instructions to modify your AppDelegate.m manually: ${constants_1.InstallationPage}`);
}

@@ -99,12 +84,13 @@ }

catch (e) {
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify index.js - ${e}.`);
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify index.js - ${e}.
See the expo-dev-client installation instructions to modify your index.js manually: ${constants_1.InstallationPage}`);
}
}
const withDevLauncherApplication = config => {
const withDevLauncherApplication = (config) => {
return config_plugins_1.withDangerousMod(config, [
'android',
async (config) => {
await editMainApplication(config, mainApplication => {
await editMainApplication(config, (mainApplication) => {
mainApplication = addJavaImports(mainApplication, [DEV_LAUNCHER_ANDROID_IMPORT]);
mainApplication = addLines(mainApplication, 'initializeFlipper\\(this', 0, [
mainApplication = utils_1.addLines(mainApplication, 'initializeFlipper\\(this', 0, [
` ${DEV_LAUNCHER_ANDROID_INIT}`,

@@ -121,6 +107,6 @@ ]);

mainApplication = addJavaImports(mainApplication, [DEV_LAUNCHER_UPDATES_ANDROID_IMPORT]);
mainApplication = addLines(mainApplication, 'initializeFlipper\\(this', 0, [
mainApplication = utils_1.addLines(mainApplication, 'initializeFlipper\\(this', 0, [
` ${DEV_LAUNCHER_UPDATES_ANDROID_INIT}`,
]);
mainApplication = replaceLine(mainApplication, 'return BuildConfig.DEBUG;', ` ${DEV_LAUNCHER_UPDATES_DEVELOPER_SUPPORT}`);
mainApplication = utils_1.replaceLine(mainApplication, 'return BuildConfig.DEBUG;', ` ${DEV_LAUNCHER_UPDATES_DEVELOPER_SUPPORT}`);
}

@@ -133,4 +119,4 @@ return mainApplication;

};
const withDevLauncherActivity = config => {
return config_plugins_1.withMainActivity(config, config => {
const withDevLauncherActivity = (config) => {
return config_plugins_1.withMainActivity(config, (config) => {
if (config.modResults.language === 'java') {

@@ -143,3 +129,3 @@ let content = addJavaImports(config.modResults.contents, [

const lines = content.split('\n');
const onCreateIndex = lines.findIndex(line => line.includes('public class MainActivity'));
const onCreateIndex = lines.findIndex((line) => line.includes('public class MainActivity'));
lines.splice(onCreateIndex + 1, 0, DEV_LAUNCHER_ON_NEW_INTENT);

@@ -149,3 +135,3 @@ content = lines.join('\n');

if (!content.includes('DevLauncherController.wrapReactActivityDelegate')) {
content = content.replace(/(new ReactActivityDelegate(.*|\s)*});$/m, DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE);
content = content.replace(/(new ReactActivityDelegate(Wrapper)?(.|\s)*\}\)?);$/mu, DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE);
}

@@ -155,3 +141,4 @@ config.modResults.contents = content;

else {
config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Cannot automatically configure MainActivity if it's not java`);
config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Cannot automatically configure MainActivity if it's not java.
See the expo-dev-client installation instructions to modify your MainActivity manually: ${constants_1.InstallationPage}`);
}

@@ -161,8 +148,9 @@ return config;

};
const withDevLauncherPodfile = config => {
const withDevLauncherPodfile = (config) => {
return config_plugins_1.withDangerousMod(config, [
'ios',
async (config) => {
await editPodfile(config, podfile => {
podfile = podfile.replace("platform :ios, '10.0'", "platform :ios, '11.0'");
await editPodfile(config, (podfile) => {
// replace all iOS versions below 12
podfile = podfile.replace(/platform :ios, '((\d\.0)|(1[0-1].0))'/, "platform :ios, '12.0'");
// Match both variations of Ruby config:

@@ -174,3 +162,3 @@ // unknown: pod 'expo-dev-launcher', path: '../node_modules/expo-dev-launcher', :configurations => :debug

const relativePath = path_1.default.relative(config.modRequest.platformProjectRoot, packagePath);
podfile = addLines(podfile, 'use_react_native', 0, [
podfile = utils_1.addLines(podfile, 'use_react_native', 0, [
` pod 'expo-dev-launcher', path: '${relativePath}', :configurations => :debug`,

@@ -185,5 +173,5 @@ ]);

};
const withErrorHandling = config => {
const withErrorHandling = (config) => {
const injectErrorHandlers = async (config) => {
await editIndex(config, index => {
await editIndex(config, (index) => {
if (!index.includes(DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS) &&

@@ -190,0 +178,0 @@ !index.includes(DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS_VIA_LAUNCHER)) {

import { ConfigPlugin } from '@expo/config-plugins';
export declare function modifyLegacyAppDelegate(appDelegate: string, expoUpdatesVersion?: string | null): string;
export declare function modifyAppDelegate(appDelegate: string, expoUpdatesVersion?: string | null): string;
export declare const withDevLauncherAppDelegate: ConfigPlugin;

@@ -6,6 +6,10 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.withDevLauncherAppDelegate = exports.modifyAppDelegate = void 0;
exports.withDevLauncherAppDelegate = exports.modifyAppDelegate = exports.modifyLegacyAppDelegate = void 0;
const config_plugins_1 = require("@expo/config-plugins");
const semver_1 = __importDefault(require("semver"));
const constants_1 = require("./constants");
const resolveExpoUpdatesVersion_1 = require("./resolveExpoUpdatesVersion");
const utils_1 = require("./utils");
const INITIALIZE_REACT_NATIVE_APP_FUNCTION = `- (RCTBridge *)initializeReactNativeApp`;
const NEW_INITIALIZE_REACT_NATIVE_APP_FUNCTION = `- (RCTBridge *)initializeReactNativeApp:(NSDictionary *)launchOptions`;
const DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL = ` #if defined(EX_DEV_LAUNCHER_ENABLED)

@@ -31,3 +35,3 @@ return [[EXDevLauncherController sharedInstance] sourceUrl];

#endif`;
const DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE = `
const DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE_LEGACY = `
#if defined(EX_DEV_LAUNCHER_ENABLED)

@@ -47,2 +51,15 @@ @implementation AppDelegate (EXDevLauncherControllerDelegate)

`;
const DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE = `
#if defined(EX_DEV_LAUNCHER_ENABLED)
@implementation AppDelegate (EXDevLauncherControllerDelegate)
- (void)devLauncherController:(EXDevLauncherController *)developmentClientController
didStartWithSuccess:(BOOL)success
{
developmentClientController.appBridge = [self initializeReactNativeApp:[EXDevLauncherController.sharedInstance getLaunchOptions]];
}
@end
#endif
`;
const DEV_LAUNCHER_APP_DELEGATE_INIT = `#if defined(EX_DEV_LAUNCHER_ENABLED)

@@ -68,4 +85,44 @@ EXDevLauncherController *controller = [EXDevLauncherController sharedInstance];

#endif`;
function modifyAppDelegate(appDelegate, expoUpdatesVersion = null) {
const shouldAddUpdatesIntegration = expoUpdatesVersion != null && semver_1.default.gt(expoUpdatesVersion, '0.6.0');
const DEV_LAUNCHER_INIT_TO_REMOVE = `RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" initialProperties:nil];
id rootViewBackgroundColor = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RCTRootViewBackgroundColor"];
if (rootViewBackgroundColor != nil) {
rootView.backgroundColor = [RCTConvert UIColor:rootViewBackgroundColor];
} else {
rootView.backgroundColor = [UIColor whiteColor];
}
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];`;
const DEV_LAUNCHER_NEW_INIT = `self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
#if defined(EX_DEV_LAUNCHER_ENABLED)
EXDevLauncherController *controller = [EXDevLauncherController sharedInstance];
[controller startWithWindow:self.window delegate:(id<EXDevLauncherControllerDelegate>)self launchOptions:launchOptions];
#else
[self initializeReactNativeApp:launchOptions];
#endif`;
const DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION = `
- (RCTBridge *)initializeReactNativeApp:(NSDictionary *)launchOptions
{
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" initialProperties:nil];
id rootViewBackgroundColor = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RCTRootViewBackgroundColor"];
if (rootViewBackgroundColor != nil) {
rootView.backgroundColor = [RCTConvert UIColor:rootViewBackgroundColor];
} else {
rootView.backgroundColor = [UIColor whiteColor];
}
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return bridge;
}
`;
function addImports(appDelegate, shouldAddUpdatesIntegration) {
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_IOS_IMPORT) &&

@@ -79,2 +136,27 @@ !appDelegate.includes(DEV_LAUNCHER_UPDATES_APP_DELEGATE_IOS_IMPORT)) {

}
return appDelegate;
}
function removeDevMenuInit(appDelegate) {
if (!appDelegate.includes(DEV_MENU_IMPORT)) {
// expo-dev-launcher is responsible for initializing the expo-dev-menu.
// We need to remove init block from AppDelegate.
appDelegate = appDelegate.replace(DEV_MENU_IOS_INIT, '');
}
return appDelegate;
}
function addDeepLinkHandler(appDelegate) {
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK)) {
appDelegate = appDelegate.replace('return [RCTLinkingManager application:application openURL:url options:options];', DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK);
}
return appDelegate;
}
function changeDebugURL(appDelegate) {
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL)) {
appDelegate = appDelegate.replace('return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];', DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL);
}
return appDelegate;
}
function modifyLegacyAppDelegate(appDelegate, expoUpdatesVersion = null) {
const shouldAddUpdatesIntegration = expoUpdatesVersion != null && semver_1.default.gt(expoUpdatesVersion, '0.6.0');
appDelegate = addImports(appDelegate, shouldAddUpdatesIntegration);
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_INIT)) {

@@ -90,21 +172,43 @@ appDelegate = appDelegate.replace(/(didFinishLaunchingWithOptions([^}])*)\[self initializeReactNativeApp\];(([^}])*})/, `$1${DEV_LAUNCHER_APP_DELEGATE_INIT}$3`);

}
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL)) {
appDelegate = appDelegate.replace('return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];', DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL);
appDelegate = changeDebugURL(appDelegate);
appDelegate = addDeepLinkHandler(appDelegate);
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE_LEGACY)) {
appDelegate += DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE_LEGACY;
}
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK)) {
appDelegate = appDelegate.replace('return [RCTLinkingManager application:application openURL:url options:options];', DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK);
appDelegate = removeDevMenuInit(appDelegate);
return appDelegate;
}
exports.modifyLegacyAppDelegate = modifyLegacyAppDelegate;
function modifyAppDelegate(appDelegate, expoUpdatesVersion = null) {
const shouldAddUpdatesIntegration = expoUpdatesVersion != null && semver_1.default.gt(expoUpdatesVersion, '0.6.0');
if (!appDelegate.includes(DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION)) {
if (appDelegate.includes(DEV_LAUNCHER_INIT_TO_REMOVE)) {
appDelegate = appDelegate.replace(DEV_LAUNCHER_INIT_TO_REMOVE, DEV_LAUNCHER_NEW_INIT);
appDelegate = utils_1.addLines(appDelegate, '@implementation AppDelegate', 1, [
DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION,
]);
}
else {
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Failed to modify AppDelegate init function.
See the expo-dev-client installation instructions to modify your AppDelegate manually: ${constants_1.InstallationPage}`);
}
}
if (shouldAddUpdatesIntegration &&
!appDelegate.includes(DEV_LAUNCHER_UPDATES_APP_DELEGATE_INIT)) {
appDelegate = appDelegate.replace('EXDevLauncherController *controller = [EXDevLauncherController sharedInstance];', DEV_LAUNCHER_UPDATES_APP_DELEGATE_INIT);
}
appDelegate = addImports(appDelegate, shouldAddUpdatesIntegration);
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE)) {
appDelegate += DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE;
}
if (!appDelegate.includes(DEV_MENU_IMPORT)) {
// expo-dev-launcher is responsible for initializing the expo-dev-menu.
// We need to remove init block from AppDelegate.
appDelegate = appDelegate.replace(DEV_MENU_IOS_INIT, '');
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK)) {
appDelegate = appDelegate.replace('return [RCTLinkingManager application:application openURL:url options:options];', DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK);
}
appDelegate = changeDebugURL(appDelegate);
appDelegate = removeDevMenuInit(appDelegate);
return appDelegate;
}
exports.modifyAppDelegate = modifyAppDelegate;
exports.withDevLauncherAppDelegate = config => {
return config_plugins_1.withAppDelegate(config, config => {
const withDevLauncherAppDelegate = (config) => {
return config_plugins_1.withAppDelegate(config, (config) => {
if (config.modResults.language === 'objc') {

@@ -118,6 +222,13 @@ let expoUpdatesVersion;

}
config.modResults.contents = modifyAppDelegate(config.modResults.contents, expoUpdatesVersion);
if (config.modResults.contents.includes(INITIALIZE_REACT_NATIVE_APP_FUNCTION) &&
!config.modResults.contents.includes(NEW_INITIALIZE_REACT_NATIVE_APP_FUNCTION)) {
config.modResults.contents = modifyLegacyAppDelegate(config.modResults.contents, expoUpdatesVersion);
}
else {
config.modResults.contents = modifyAppDelegate(config.modResults.contents, expoUpdatesVersion);
}
}
else {
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', 'Swift AppDelegate files are not supported yet.');
config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Swift AppDelegate files are not supported yet.
See the expo-dev-client installation instructions to modify your AppDelegate manually: ${constants_1.InstallationPage}`);
}

@@ -127,1 +238,2 @@ return config;

};
exports.withDevLauncherAppDelegate = withDevLauncherAppDelegate;

@@ -14,3 +14,5 @@ import {

import { InstallationPage } from './constants';
import { resolveExpoUpdatesVersion } from './resolveExpoUpdatesVersion';
import { addLines, replaceLine } from './utils';
import { withDevLauncherAppDelegate } from './withDevLauncherAppDelegate';

@@ -50,31 +52,5 @@

function addLines(content: string, find: string | RegExp, offset: number, toAdd: string[]) {
const lines = content.split('\n');
let lineIndex = lines.findIndex(line => line.match(find));
for (const newLine of toAdd) {
if (!content.includes(newLine)) {
lines.splice(lineIndex + offset, 0, newLine);
lineIndex++;
}
}
return lines.join('\n');
}
function replaceLine(content: string, find: string | RegExp, replace: string) {
const lines = content.split('\n');
if (!content.includes(replace)) {
const lineIndex = lines.findIndex(line => line.match(find));
lines.splice(lineIndex, 1, replace);
}
return lines.join('\n');
}
function addJavaImports(javaSource: string, javaImports: string[]): string {
const lines = javaSource.split('\n');
const lineIndexWithPackageDeclaration = lines.findIndex(line => line.match(/^package .*;$/));
const lineIndexWithPackageDeclaration = lines.findIndex((line) => line.match(/^package .*;$/));
for (const javaImport of javaImports) {

@@ -107,5 +83,6 @@ if (!javaSource.includes(javaImport)) {

} catch (e) {
WarningAggregator.addWarningIOS(
WarningAggregator.addWarningAndroid(
'expo-dev-launcher',
`Couldn't modify MainApplication.java - ${e}.`
`Couldn't modify MainApplication.java - ${e}.
See the expo-dev-client installation instructions to modify your MainApplication.java manually: ${InstallationPage}`
);

@@ -121,3 +98,7 @@ }

} catch (e) {
WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify AppDelegate.m - ${e}.`);
WarningAggregator.addWarningIOS(
'expo-dev-launcher',
`Couldn't modify AppDelegate.m - ${e}.
See the expo-dev-client installation instructions to modify your AppDelegate.m manually: ${InstallationPage}`
);
}

@@ -132,11 +113,15 @@ }

} catch (e) {
WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify index.js - ${e}.`);
WarningAggregator.addWarningIOS(
'expo-dev-launcher',
`Couldn't modify index.js - ${e}.
See the expo-dev-client installation instructions to modify your index.js manually: ${InstallationPage}`
);
}
}
const withDevLauncherApplication: ConfigPlugin = config => {
const withDevLauncherApplication: ConfigPlugin = (config) => {
return withDangerousMod(config, [
'android',
async config => {
await editMainApplication(config, mainApplication => {
async (config) => {
await editMainApplication(config, (mainApplication) => {
mainApplication = addJavaImports(mainApplication, [DEV_LAUNCHER_ANDROID_IMPORT]);

@@ -176,4 +161,4 @@

const withDevLauncherActivity: ConfigPlugin = config => {
return withMainActivity(config, config => {
const withDevLauncherActivity: ConfigPlugin = (config) => {
return withMainActivity(config, (config) => {
if (config.modResults.language === 'java') {

@@ -187,3 +172,3 @@ let content = addJavaImports(config.modResults.contents, [

const lines = content.split('\n');
const onCreateIndex = lines.findIndex(line => line.includes('public class MainActivity'));
const onCreateIndex = lines.findIndex((line) => line.includes('public class MainActivity'));

@@ -197,3 +182,3 @@ lines.splice(onCreateIndex + 1, 0, DEV_LAUNCHER_ON_NEW_INTENT);

content = content.replace(
/(new ReactActivityDelegate(.*|\s)*});$/m,
/(new ReactActivityDelegate(Wrapper)?(.|\s)*\}\)?);$/mu,
DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE

@@ -207,3 +192,4 @@ );

'expo-dev-launcher',
`Cannot automatically configure MainActivity if it's not java`
`Cannot automatically configure MainActivity if it's not java.
See the expo-dev-client installation instructions to modify your MainActivity manually: ${InstallationPage}`
);

@@ -216,8 +202,9 @@ }

const withDevLauncherPodfile: ConfigPlugin = config => {
const withDevLauncherPodfile: ConfigPlugin = (config) => {
return withDangerousMod(config, [
'ios',
async config => {
await editPodfile(config, podfile => {
podfile = podfile.replace("platform :ios, '10.0'", "platform :ios, '11.0'");
async (config) => {
await editPodfile(config, (podfile) => {
// replace all iOS versions below 12
podfile = podfile.replace(/platform :ios, '((\d\.0)|(1[0-1].0))'/, "platform :ios, '12.0'");
// Match both variations of Ruby config:

@@ -244,5 +231,5 @@ // unknown: pod 'expo-dev-launcher', path: '../node_modules/expo-dev-launcher', :configurations => :debug

const withErrorHandling: ConfigPlugin = config => {
const withErrorHandling: ConfigPlugin = (config) => {
const injectErrorHandlers = async (config: ExportedConfigWithProps) => {
await editIndex(config, index => {
await editIndex(config, (index) => {
if (

@@ -249,0 +236,0 @@ !index.includes(DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS) &&

import { ConfigPlugin, WarningAggregator, withAppDelegate } from '@expo/config-plugins';
import semver from 'semver';
import { InstallationPage } from './constants';
import { resolveExpoUpdatesVersion } from './resolveExpoUpdatesVersion';
import { addLines } from './utils';
const INITIALIZE_REACT_NATIVE_APP_FUNCTION = `- (RCTBridge *)initializeReactNativeApp`;
const NEW_INITIALIZE_REACT_NATIVE_APP_FUNCTION = `- (RCTBridge *)initializeReactNativeApp:(NSDictionary *)launchOptions`;
const DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL = ` #if defined(EX_DEV_LAUNCHER_ENABLED)

@@ -26,3 +31,3 @@ return [[EXDevLauncherController sharedInstance] sourceUrl];

#endif`;
const DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE = `
const DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE_LEGACY = `
#if defined(EX_DEV_LAUNCHER_ENABLED)

@@ -42,2 +47,17 @@ @implementation AppDelegate (EXDevLauncherControllerDelegate)

`;
const DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE = `
#if defined(EX_DEV_LAUNCHER_ENABLED)
@implementation AppDelegate (EXDevLauncherControllerDelegate)
- (void)devLauncherController:(EXDevLauncherController *)developmentClientController
didStartWithSuccess:(BOOL)success
{
developmentClientController.appBridge = [self initializeReactNativeApp:[EXDevLauncherController.sharedInstance getLaunchOptions]];
}
@end
#endif
`;
const DEV_LAUNCHER_APP_DELEGATE_INIT = `#if defined(EX_DEV_LAUNCHER_ENABLED)

@@ -66,6 +86,47 @@ EXDevLauncherController *controller = [EXDevLauncherController sharedInstance];

export function modifyAppDelegate(appDelegate: string, expoUpdatesVersion: string | null = null) {
const shouldAddUpdatesIntegration =
expoUpdatesVersion != null && semver.gt(expoUpdatesVersion, '0.6.0');
const DEV_LAUNCHER_INIT_TO_REMOVE = `RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" initialProperties:nil];
id rootViewBackgroundColor = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RCTRootViewBackgroundColor"];
if (rootViewBackgroundColor != nil) {
rootView.backgroundColor = [RCTConvert UIColor:rootViewBackgroundColor];
} else {
rootView.backgroundColor = [UIColor whiteColor];
}
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];`;
const DEV_LAUNCHER_NEW_INIT = `self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
#if defined(EX_DEV_LAUNCHER_ENABLED)
EXDevLauncherController *controller = [EXDevLauncherController sharedInstance];
[controller startWithWindow:self.window delegate:(id<EXDevLauncherControllerDelegate>)self launchOptions:launchOptions];
#else
[self initializeReactNativeApp:launchOptions];
#endif`;
const DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION = `
- (RCTBridge *)initializeReactNativeApp:(NSDictionary *)launchOptions
{
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" initialProperties:nil];
id rootViewBackgroundColor = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RCTRootViewBackgroundColor"];
if (rootViewBackgroundColor != nil) {
rootView.backgroundColor = [RCTConvert UIColor:rootViewBackgroundColor];
} else {
rootView.backgroundColor = [UIColor whiteColor];
}
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return bridge;
}
`;
function addImports(appDelegate: string, shouldAddUpdatesIntegration: boolean): string {
if (

@@ -87,2 +148,43 @@ !appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_IOS_IMPORT) &&

return appDelegate;
}
function removeDevMenuInit(appDelegate: string): string {
if (!appDelegate.includes(DEV_MENU_IMPORT)) {
// expo-dev-launcher is responsible for initializing the expo-dev-menu.
// We need to remove init block from AppDelegate.
appDelegate = appDelegate.replace(DEV_MENU_IOS_INIT, '');
}
return appDelegate;
}
function addDeepLinkHandler(appDelegate: string): string {
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK)) {
appDelegate = appDelegate.replace(
'return [RCTLinkingManager application:application openURL:url options:options];',
DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK
);
}
return appDelegate;
}
function changeDebugURL(appDelegate: string): string {
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL)) {
appDelegate = appDelegate.replace(
'return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];',
DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL
);
}
return appDelegate;
}
export function modifyLegacyAppDelegate(
appDelegate: string,
expoUpdatesVersion: string | null = null
) {
const shouldAddUpdatesIntegration =
expoUpdatesVersion != null && semver.gt(expoUpdatesVersion, '0.6.0');
appDelegate = addImports(appDelegate, shouldAddUpdatesIntegration);
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_INIT)) {

@@ -112,16 +214,44 @@ appDelegate = appDelegate.replace(

if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL)) {
appDelegate = appDelegate.replace(
'return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];',
DEV_LAUNCHER_APP_DELEGATE_SOURCE_FOR_URL
);
appDelegate = changeDebugURL(appDelegate);
appDelegate = addDeepLinkHandler(appDelegate);
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE_LEGACY)) {
appDelegate += DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE_LEGACY;
}
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK)) {
appDelegate = removeDevMenuInit(appDelegate);
return appDelegate;
}
export function modifyAppDelegate(appDelegate: string, expoUpdatesVersion: string | null = null) {
const shouldAddUpdatesIntegration =
expoUpdatesVersion != null && semver.gt(expoUpdatesVersion, '0.6.0');
if (!appDelegate.includes(DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION)) {
if (appDelegate.includes(DEV_LAUNCHER_INIT_TO_REMOVE)) {
appDelegate = appDelegate.replace(DEV_LAUNCHER_INIT_TO_REMOVE, DEV_LAUNCHER_NEW_INIT);
appDelegate = addLines(appDelegate, '@implementation AppDelegate', 1, [
DEV_LAUNCHER_INITIALIZE_REACT_NATIVE_APP_FUNCTION_DEFINITION,
]);
} else {
WarningAggregator.addWarningIOS(
'expo-dev-launcher',
`Failed to modify AppDelegate init function.
See the expo-dev-client installation instructions to modify your AppDelegate manually: ${InstallationPage}`
);
}
}
if (
shouldAddUpdatesIntegration &&
!appDelegate.includes(DEV_LAUNCHER_UPDATES_APP_DELEGATE_INIT)
) {
appDelegate = appDelegate.replace(
'return [RCTLinkingManager application:application openURL:url options:options];',
DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK
'EXDevLauncherController *controller = [EXDevLauncherController sharedInstance];',
DEV_LAUNCHER_UPDATES_APP_DELEGATE_INIT
);
}
appDelegate = addImports(appDelegate, shouldAddUpdatesIntegration);
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE)) {

@@ -131,13 +261,16 @@ appDelegate += DEV_LAUNCHER_APP_DELEGATE_CONTROLLER_DELEGATE;

if (!appDelegate.includes(DEV_MENU_IMPORT)) {
// expo-dev-launcher is responsible for initializing the expo-dev-menu.
// We need to remove init block from AppDelegate.
appDelegate = appDelegate.replace(DEV_MENU_IOS_INIT, '');
if (!appDelegate.includes(DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK)) {
appDelegate = appDelegate.replace(
'return [RCTLinkingManager application:application openURL:url options:options];',
DEV_LAUNCHER_APP_DELEGATE_ON_DEEP_LINK
);
}
appDelegate = changeDebugURL(appDelegate);
appDelegate = removeDevMenuInit(appDelegate);
return appDelegate;
}
export const withDevLauncherAppDelegate: ConfigPlugin = config => {
return withAppDelegate(config, config => {
export const withDevLauncherAppDelegate: ConfigPlugin = (config) => {
return withAppDelegate(config, (config) => {
if (config.modResults.language === 'objc') {

@@ -153,10 +286,22 @@ let expoUpdatesVersion;

}
config.modResults.contents = modifyAppDelegate(
config.modResults.contents,
expoUpdatesVersion
);
if (
config.modResults.contents.includes(INITIALIZE_REACT_NATIVE_APP_FUNCTION) &&
!config.modResults.contents.includes(NEW_INITIALIZE_REACT_NATIVE_APP_FUNCTION)
) {
config.modResults.contents = modifyLegacyAppDelegate(
config.modResults.contents,
expoUpdatesVersion
);
} else {
config.modResults.contents = modifyAppDelegate(
config.modResults.contents,
expoUpdatesVersion
);
}
} else {
WarningAggregator.addWarningIOS(
'expo-dev-launcher',
'Swift AppDelegate files are not supported yet.'
`Swift AppDelegate files are not supported yet.
See the expo-dev-client installation instructions to modify your AppDelegate manually: ${InstallationPage}`
);

@@ -163,0 +308,0 @@ }

# expo-dev-launcher
This is a pre-release version of the Expo dev launcher package for testing.
`expo-dev-launcher` is an npm package installable in any Expo or React Native project. Once installed, any Debug builds of your application will gain the ability to load projects from Expo CLI. Release builds of your application will not change other than the addition of a few header files. This package is intended to be included in your project through [`expo-dev-client`](https://docs.expo.io/clients/introduction/).

@@ -5,0 +5,0 @@ # ⚙️ Installation

@@ -5,2 +5,3 @@ // Similar interface to the one used in expo modules.

let isErrorHandlingEnabled = true;
let wasHit = false; // whether the original error handler was called

@@ -44,5 +45,11 @@ const unavailableErrorPossibleSolutions = `Some possible solutions:

if (error instanceof Error) {
// Suppresses `"main" has not been registered` error only if it was caused by a different error.
// Otherwise, we want to show it, cause the user may forget to call `AppRegistry.registerComponent`.
if (wasHit && error.message?.includes('has not been registered. This can happen if')) {
return;
}
customizeError(error);
}
wasHit = true;
originalHandler(error, isFatal);

@@ -49,0 +56,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc