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