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