UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

366 lines (295 loc) 11.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; function _path() { const data = _interopRequireDefault(require("path")); _path = function () { return data; }; return data; } function _execa() { const data = _interopRequireDefault(require("execa")); _execa = function () { return data; }; return data; } function _chalk() { const data = _interopRequireDefault(require("chalk")); _chalk = function () { return data; }; return data; } function _fs() { const data = _interopRequireDefault(require("fs")); _fs = function () { return data; }; return data; } var _adb = _interopRequireDefault(require("./adb")); var _runOnAllDevices = _interopRequireDefault(require("./runOnAllDevices")); var _tryRunAdbReverse = _interopRequireDefault(require("./tryRunAdbReverse")); var _tryLaunchAppOnDevice = _interopRequireDefault(require("./tryLaunchAppOnDevice")); var _getAdbPath = _interopRequireDefault(require("./getAdbPath")); function _cliTools() { const data = require("@react-native-community/cli-tools"); _cliTools = function () { return data; }; return data; } var _warnAboutManuallyLinkedLibs = _interopRequireDefault(require("../../link/warnAboutManuallyLinkedLibs")); var _getAndroidProject = require("../../utils/getAndroidProject"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ function displayWarnings(config, args) { (0, _warnAboutManuallyLinkedLibs.default)(config); if (args.appFolder) { _cliTools().logger.warn('Using deprecated "--appFolder" flag. Use "project.android.appName" in react-native.config.js instead.'); } if (args.root) { _cliTools().logger.warn('Using deprecated "--root" flag. App root is discovered automatically. Alternatively, set "project.android.sourceDir" in react-native.config.js.'); } } /** * Starts the app on a connected Android emulator or device. */ async function runAndroid(_argv, config, args) { displayWarnings(config, args); const androidProject = (0, _getAndroidProject.getAndroidProject)(config); if (args.jetifier) { _cliTools().logger.info(`Running ${_chalk().default.bold('jetifier')} to migrate libraries to AndroidX. ${_chalk().default.dim('You can disable it using "--no-jetifier" flag.')}`); try { await (0, _execa().default)(require.resolve('jetifier/bin/jetify'), { stdio: 'inherit' }); } catch (error) { throw new (_cliTools().CLIError)('Failed to run jetifier.', error); } } if (!args.packager) { return buildAndRun(args, androidProject); } return (0, _cliTools().isPackagerRunning)(args.port).then(result => { if (result === 'running') { _cliTools().logger.info('JS server already running.'); } else if (result === 'unrecognized') { _cliTools().logger.warn('JS server not recognized, continuing with build...'); } else { // result == 'not_running' _cliTools().logger.info('Starting JS server...'); try { startServerInNewWindow(args.port, args.terminal, config.reactNativePath); } catch (error) { _cliTools().logger.warn(`Failed to automatically start the packager server. Please run "react-native start" manually. Error details: ${error.message}`); } } return buildAndRun(args, androidProject); }); } // Builds the app and runs it on a connected emulator / device. function buildAndRun(args, androidProject) { process.chdir(androidProject.sourceDir); const cmd = process.platform.startsWith('win') ? 'gradlew.bat' : './gradlew'; const { appFolder } = args; const packageName = (0, _getAndroidProject.getPackageName)(androidProject, appFolder); const adbPath = (0, _getAdbPath.default)(); if (args.deviceId) { return runOnSpecificDevice(args, cmd, packageName, adbPath, androidProject); } else { return (0, _runOnAllDevices.default)(args, cmd, packageName, adbPath, androidProject); } } function runOnSpecificDevice(args, gradlew, packageName, adbPath, androidProject) { const devices = _adb.default.getDevices(adbPath); const { deviceId } = args; if (devices.length > 0 && deviceId) { if (devices.indexOf(deviceId) !== -1) { buildApk(gradlew, androidProject.sourceDir); installAndLaunchOnDevice(args, deviceId, packageName, adbPath, androidProject); } else { _cliTools().logger.error(`Could not find device with the id: "${deviceId}". Please choose one of the following:`, ...devices); } } else { _cliTools().logger.error('No Android device or emulator connected.'); } } function buildApk(gradlew, sourceDir) { try { // using '-x lint' in order to ignore linting errors while building the apk const gradleArgs = ['build', '-x', 'lint']; _cliTools().logger.info('Building the app...'); _cliTools().logger.debug(`Running command "${gradlew} ${gradleArgs.join(' ')}"`); _execa().default.sync(gradlew, gradleArgs, { stdio: 'inherit', cwd: sourceDir }); } catch (error) { throw new (_cliTools().CLIError)('Failed to build the app.', error); } } function tryInstallAppOnDevice(args, adbPath, device, androidProject) { try { // "app" is usually the default value for Android apps with only 1 app const { appName, sourceDir } = androidProject; const { appFolder } = args; const variant = args.variant.toLowerCase(); const buildDirectory = `${sourceDir}/${appName}/build/outputs/apk/${variant}`; const apkFile = getInstallApkName(appFolder || appName, // TODO: remove appFolder adbPath, variant, device, buildDirectory); const pathToApk = `${buildDirectory}/${apkFile}`; const adbArgs = ['-s', device, 'install', '-r', '-d', pathToApk]; _cliTools().logger.info(`Installing the app on the device "${device}"...`); _cliTools().logger.debug(`Running command "cd android && adb -s ${device} install -r -d ${pathToApk}"`); _execa().default.sync(adbPath, adbArgs, { stdio: 'inherit' }); } catch (error) { throw new (_cliTools().CLIError)('Failed to install the app on the device.', error); } } function getInstallApkName(appName, adbPath, variant, device, buildDirectory) { const availableCPUs = _adb.default.getAvailableCPUs(adbPath, device); // check if there is an apk file like app-armeabi-v7a-debug.apk for (const availableCPU of availableCPUs.concat('universal')) { const apkName = `${appName}-${availableCPU}-${variant}.apk`; if (_fs().default.existsSync(`${buildDirectory}/${apkName}`)) { return apkName; } } // check if there is a default file like app-debug.apk const apkName = `${appName}-${variant}.apk`; if (_fs().default.existsSync(`${buildDirectory}/${apkName}`)) { return apkName; } throw new (_cliTools().CLIError)('Could not find the correct install APK file.'); } function installAndLaunchOnDevice(args, selectedDevice, packageName, adbPath, androidProject) { (0, _tryRunAdbReverse.default)(args.port, selectedDevice); tryInstallAppOnDevice(args, adbPath, selectedDevice, androidProject); (0, _tryLaunchAppOnDevice.default)(selectedDevice, packageName, adbPath, args); } function startServerInNewWindow(port, terminal, reactNativePath) { /** * Set up OS-specific filenames and commands */ const isWindows = /^win/.test(process.platform); const scriptFile = isWindows ? 'launchPackager.bat' : 'launchPackager.command'; const packagerEnvFilename = isWindows ? '.packager.bat' : '.packager.env'; const portExportContent = isWindows ? `set RCT_METRO_PORT=${port}` : `export RCT_METRO_PORT=${port}`; /** * Set up the `.packager.(env|bat)` file to ensure the packager starts on the right port. */ const launchPackagerScript = _path().default.join(reactNativePath, `scripts/${scriptFile}`); /** * Set up the `launchpackager.(command|bat)` file. * It lives next to `.packager.(bat|env)` */ const scriptsDir = _path().default.dirname(launchPackagerScript); const packagerEnvFile = _path().default.join(scriptsDir, packagerEnvFilename); const procConfig = { cwd: scriptsDir }; /** * Ensure we overwrite file by passing the `w` flag */ _fs().default.writeFileSync(packagerEnvFile, portExportContent, { encoding: 'utf8', flag: 'w' }); if (process.platform === 'darwin') { try { return _execa().default.sync('open', ['-a', terminal, launchPackagerScript], procConfig); } catch (error) { return _execa().default.sync('open', [launchPackagerScript], procConfig); } } if (process.platform === 'linux') { try { return _execa().default.sync(terminal, ['-e', `sh ${launchPackagerScript}`], { ...procConfig, detached: true }); } catch (error) { // By default, the child shell process will be attached to the parent return _execa().default.sync('sh', [launchPackagerScript], procConfig); } } if (/^win/.test(process.platform)) { // Awaiting this causes the CLI to hang indefinitely, so this must execute without await. return (0, _execa().default)('cmd.exe', ['/C', launchPackagerScript], { ...procConfig, detached: true, stdio: 'ignore' }); } _cliTools().logger.error(`Cannot start the packager. Unknown platform ${process.platform}`); return; } var _default = { name: 'run-android', description: 'builds your app and starts it on a connected Android emulator or device', func: runAndroid, options: [{ name: '--root <string>', description: '[DEPRECATED - root is discovered automatically] Override the root directory for the android build (which contains the android directory)', default: '' }, { name: '--variant <string>', description: "Specify your app's build variant", default: 'debug' }, { name: '--appFolder <string>', description: '[DEPRECATED – use "project.android.appName" in react-native.config.js] Specify a different application folder name for the android source. If not, we assume is "app"' }, { name: '--appId <string>', description: 'Specify an applicationId to launch after build. If not specified, `package` from AndroidManifest.xml will be used.', default: '' }, { name: '--appIdSuffix <string>', description: 'Specify an applicationIdSuffix to launch after build.', default: '' }, { name: '--main-activity <string>', description: 'Name of the activity to start', default: 'MainActivity' }, { name: '--deviceId <string>', description: 'builds your app and starts it on a specific device/simulator with the ' + 'given device id (listed by running "adb devices" on the command line).' }, { name: '--no-packager', description: 'Do not launch packager while building' }, { name: '--port <number>', default: process.env.RCT_METRO_PORT || 8081, parse: Number }, { name: '--terminal <string>', description: 'Launches the Metro Bundler in a new window using the specified terminal path.', default: (0, _cliTools().getDefaultUserTerminal)() }, { name: '--tasks <list>', description: 'Run custom Gradle tasks. By default it\'s "installDebug"', parse: val => val.split(',') }, { name: '--no-jetifier', description: 'Do not run "jetifier" – the AndroidX transition tool. By default it runs before Gradle to ease working with libraries that don\'t support AndroidX yet. See more at: https://www.npmjs.com/package/jetifier.' }] }; exports.default = _default; //# sourceMappingURL=index.js.map