1"use strict"; 2var __importDefault = (this && this.__importDefault) || function (mod) { 3 return (mod && mod.__esModule) ? mod : { "default": mod }; 4}; 5Object.defineProperty(exports, "__esModule", { value: true }); 6exports.createExampleApp = void 0; 7const spawn_async_1 = __importDefault(require("@expo/spawn-async")); 8const fs_extra_1 = __importDefault(require("fs-extra")); 9const getenv_1 = __importDefault(require("getenv")); 10const os_1 = __importDefault(require("os")); 11const path_1 = __importDefault(require("path")); 12const packageManager_1 = require("./packageManager"); 13const utils_1 = require("./utils"); 14const debug = require('debug')('create-expo-module:createExampleApp'); 15// These dependencies will be removed from the example app (`expo init` adds them) 16const DEPENDENCIES_TO_REMOVE = ['expo-status-bar', 'expo-splash-screen']; 17const EXPO_BETA = getenv_1.default.boolish('EXPO_BETA', false); 18/** 19 * Initializes a new Expo project as an example app. 20 */ 21async function createExampleApp(data, targetDir, packageManager) { 22 // Package name for the example app 23 const exampleProjectSlug = `${data.project.slug}-example`; 24 // `expo init` creates a new folder with the same name as the project slug 25 const appTmpPath = path_1.default.join(targetDir, exampleProjectSlug); 26 // Path to the target example dir 27 const appTargetPath = path_1.default.join(targetDir, 'example'); 28 if (!(await fs_extra_1.default.pathExists(appTargetPath))) { 29 // The template doesn't include the example app, so just skip this phase 30 return; 31 } 32 await (0, utils_1.newStep)('Initializing the example app', async (step) => { 33 const templateVersion = EXPO_BETA ? 'next' : 'latest'; 34 const template = `expo-template-blank-typescript@${templateVersion}`; 35 debug(`Using example template: ${template}`); 36 await (0, spawn_async_1.default)(packageManager, ['create', 'expo-app', '--', exampleProjectSlug, '--template', template, '--yes'], { 37 cwd: targetDir, 38 stdio: 'ignore', 39 }); 40 step.succeed('Initialized the example app'); 41 }); 42 await (0, utils_1.newStep)('Configuring the example app', async (step) => { 43 // "example" folder already exists and contains template files, 44 // that should replace these created by `expo init`. 45 await moveFiles(appTargetPath, appTmpPath); 46 // Cleanup the "example" dir 47 await fs_extra_1.default.rmdir(appTargetPath); 48 // Clean up the ".git" from example app 49 // note, this directory has contents, rmdir will throw 50 await fs_extra_1.default.remove(path_1.default.join(appTmpPath, '.git')); 51 // Move the temporary example app to "example" dir 52 await fs_extra_1.default.rename(appTmpPath, appTargetPath); 53 await addMissingAppConfigFields(appTargetPath, data); 54 step.succeed('Configured the example app'); 55 }); 56 await prebuildExampleApp(appTargetPath); 57 await modifyPackageJson(appTargetPath); 58 await (0, utils_1.newStep)('Installing dependencies in the example app', async (step) => { 59 await (0, packageManager_1.installDependencies)(packageManager, appTargetPath); 60 if (os_1.default.platform() === 'darwin') { 61 await podInstall(appTargetPath); 62 step.succeed('Installed dependencies in the example app'); 63 } 64 else { 65 step.succeed('Installed dependencies in the example app (skipped installing CocoaPods)'); 66 } 67 }); 68} 69exports.createExampleApp = createExampleApp; 70/** 71 * Copies files from one directory to another. 72 */ 73async function moveFiles(fromPath, toPath) { 74 for (const file of await fs_extra_1.default.readdir(fromPath)) { 75 await fs_extra_1.default.move(path_1.default.join(fromPath, file), path_1.default.join(toPath, file), { 76 overwrite: true, 77 }); 78 } 79} 80/** 81 * Adds missing configuration that are required to run `npx expo prebuild`. 82 */ 83async function addMissingAppConfigFields(appPath, data) { 84 const appConfigPath = path_1.default.join(appPath, 'app.json'); 85 const appConfig = await fs_extra_1.default.readJson(appConfigPath); 86 const appId = `${data.project.package}.example`; 87 // Android package name needs to be added to app.json 88 if (!appConfig.expo.android) { 89 appConfig.expo.android = {}; 90 } 91 appConfig.expo.android.package = appId; 92 // Specify iOS bundle identifier 93 if (!appConfig.expo.ios) { 94 appConfig.expo.ios = {}; 95 } 96 appConfig.expo.ios.bundleIdentifier = appId; 97 await fs_extra_1.default.writeJson(appConfigPath, appConfig, { 98 spaces: 2, 99 }); 100} 101/** 102 * Applies necessary changes to **package.json** of the example app. 103 * It means setting the autolinking config and removing unnecessary dependencies. 104 */ 105async function modifyPackageJson(appPath) { 106 const packageJsonPath = path_1.default.join(appPath, 'package.json'); 107 const packageJson = await fs_extra_1.default.readJson(packageJsonPath); 108 if (!packageJson.expo) { 109 packageJson.expo = {}; 110 } 111 // Set the native modules dir to the root folder, 112 // so that the autolinking can detect and link the module. 113 packageJson.expo.autolinking = { 114 nativeModulesDir: '..', 115 }; 116 // Remove unnecessary dependencies 117 for (const dependencyToRemove of DEPENDENCIES_TO_REMOVE) { 118 delete packageJson.dependencies[dependencyToRemove]; 119 } 120 await fs_extra_1.default.writeJson(packageJsonPath, packageJson, { 121 spaces: 2, 122 }); 123} 124/** 125 * Runs `npx expo prebuild` in the example app. 126 */ 127async function prebuildExampleApp(exampleAppPath) { 128 await (0, utils_1.newStep)('Prebuilding the example app', async (step) => { 129 await (0, spawn_async_1.default)('npx', ['expo', 'prebuild', '--no-install'], { 130 cwd: exampleAppPath, 131 stdio: ['ignore', 'ignore', 'pipe'], 132 }); 133 step.succeed('Prebuilt the example app'); 134 }); 135} 136/** 137 * Runs `pod install` in the iOS project at the given path. 138 */ 139async function podInstall(appPath) { 140 await (0, spawn_async_1.default)('pod', ['install'], { 141 cwd: path_1.default.join(appPath, 'ios'), 142 stdio: ['ignore', 'ignore', 'pipe'], 143 }); 144} 145//# sourceMappingURL=createExampleApp.js.map