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.convertPackageNameToProjectName = exports.resolveModuleAsync = exports.generatePackageListAsync = void 0; 7const fast_glob_1 = __importDefault(require("fast-glob")); 8const fs_extra_1 = __importDefault(require("fs-extra")); 9const path_1 = __importDefault(require("path")); 10/** 11 * Generates Java file that contains all autolinked packages. 12 */ 13async function generatePackageListAsync(modules, targetPath, namespace) { 14 const generatedFileContent = await generatePackageListFileContentAsync(modules, namespace); 15 await fs_extra_1.default.outputFile(targetPath, generatedFileContent); 16} 17exports.generatePackageListAsync = generatePackageListAsync; 18async function findGradleFilesAsync(revision) { 19 const configGradlePaths = revision.config?.androidGradlePaths(); 20 if (configGradlePaths && configGradlePaths.length) { 21 return configGradlePaths; 22 } 23 const buildGradleFiles = await (0, fast_glob_1.default)('*/build.gradle', { 24 cwd: revision.path, 25 ignore: ['**/node_modules/**'], 26 }); 27 return buildGradleFiles; 28} 29async function resolveModuleAsync(packageName, revision) { 30 // TODO: Relative source dir should be configurable through the module config. 31 // Don't link itself... :D 32 if (packageName === '@unimodules/react-native-adapter') { 33 return null; 34 } 35 const buildGradleFiles = await findGradleFilesAsync(revision); 36 // Just in case where the module doesn't have its own `build.gradle`. 37 if (!buildGradleFiles.length) { 38 return null; 39 } 40 const projects = buildGradleFiles.map((buildGradleFile) => { 41 const gradleFilePath = path_1.default.join(revision.path, buildGradleFile); 42 return { 43 name: convertPackageNameToProjectName(packageName, path_1.default.relative(revision.path, gradleFilePath)), 44 sourceDir: path_1.default.dirname(gradleFilePath), 45 }; 46 }); 47 const plugins = (revision.config?.androidGradlePlugins() ?? []).map(({ id, group, sourceDir }) => ({ 48 id, 49 group, 50 sourceDir: path_1.default.join(revision.path, sourceDir), 51 })); 52 return { 53 packageName, 54 projects, 55 ...(plugins.length > 0 ? { plugins } : {}), 56 modules: revision.config?.androidModules() ?? [], 57 }; 58} 59exports.resolveModuleAsync = resolveModuleAsync; 60/** 61 * Generates the string to put into the generated package list. 62 */ 63async function generatePackageListFileContentAsync(modules, namespace) { 64 // TODO: Instead of ignoring `expo` here, make the package class paths configurable from `expo-module.config.json`. 65 const packagesClasses = await findAndroidPackagesAsync(modules.filter((module) => module.packageName !== 'expo')); 66 const modulesClasses = await findAndroidModules(modules); 67 return `package ${namespace}; 68 69import java.util.Arrays; 70import java.util.List; 71import expo.modules.core.interfaces.Package; 72import expo.modules.kotlin.modules.Module; 73import expo.modules.kotlin.ModulesProvider; 74 75public class ExpoModulesPackageList implements ModulesProvider { 76 private static class LazyHolder { 77 static final List<Package> packagesList = Arrays.<Package>asList( 78${packagesClasses.map((packageClass) => ` new ${packageClass}()`).join(',\n')} 79 ); 80 81 static final List<Class<? extends Module>> modulesList = Arrays.<Class<? extends Module>>asList( 82 ${modulesClasses.map((moduleClass) => ` ${moduleClass}.class`).join(',\n')} 83 ); 84 } 85 86 public static List<Package> getPackageList() { 87 return LazyHolder.packagesList; 88 } 89 90 @Override 91 public List<Class<? extends Module>> getModulesList() { 92 return LazyHolder.modulesList; 93 } 94} 95`; 96} 97function findAndroidModules(modules) { 98 const modulesToProvide = modules.filter((module) => module.modules.length > 0); 99 const classNames = [].concat(...modulesToProvide.map((module) => module.modules)); 100 return classNames; 101} 102async function findAndroidPackagesAsync(modules) { 103 const classes = []; 104 const flattenedSourceDirList = []; 105 for (const module of modules) { 106 for (const project of module.projects) { 107 flattenedSourceDirList.push(project.sourceDir); 108 } 109 } 110 await Promise.all(flattenedSourceDirList.map(async (sourceDir) => { 111 const files = await (0, fast_glob_1.default)('**/*Package.{java,kt}', { 112 cwd: sourceDir, 113 }); 114 for (const file of files) { 115 const fileContent = await fs_extra_1.default.readFile(path_1.default.join(sourceDir, file), 'utf8'); 116 const packageRegex = (() => { 117 if (process.env.EXPO_SHOULD_USE_LEGACY_PACKAGE_INTERFACE) { 118 return /\bimport\s+org\.unimodules\.core\.(interfaces\.Package|BasePackage)\b/; 119 } 120 else { 121 return /\bimport\s+expo\.modules\.core\.(interfaces\.Package|BasePackage)\b/; 122 } 123 })(); 124 // Very naive check to skip non-expo packages 125 if (!packageRegex.test(fileContent)) { 126 continue; 127 } 128 const classPathMatches = fileContent.match(/^package ([\w.]+)\b/m); 129 if (classPathMatches) { 130 const basename = path_1.default.basename(file, path_1.default.extname(file)); 131 classes.push(`${classPathMatches[1]}.${basename}`); 132 } 133 } 134 })); 135 return classes.sort(); 136} 137/** 138 * Converts the package name and gradle file path to Android's project name. 139 * `$` to indicate subprojects 140 * `/` path will transform as `-` 141 * 142 * Example: `@expo/example` + `android/build.gradle` → `expo-example` 143 * 144 * Example: multiple projects 145 * - `expo-test` + `android/build.gradle` → `react-native-third-party` 146 * - `expo-test` + `subproject/build.gradle` → `react-native-third-party$subproject` 147 */ 148function convertPackageNameToProjectName(packageName, buildGradleFile) { 149 const name = packageName.replace(/^@/g, '').replace(/\W+/g, '-'); 150 const baseDir = path_1.default.dirname(buildGradleFile).replace(/\//g, '-'); 151 return baseDir === 'android' ? name : `${name}$${baseDir}`; 152} 153exports.convertPackageNameToProjectName = convertPackageNameToProjectName; 154//# sourceMappingURL=android.js.map