UNPKG

create-expo-cljs-app

Version:

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

237 lines 11.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generatePackageListAsync = exports.resolveModulesAsync = exports.verifySearchResults = exports.mergeLinkingOptionsAsync = exports.findModulesAsync = exports.findDefaultPathsAsync = exports.resolveSearchPathsAsync = void 0; const chalk_1 = __importDefault(require("chalk")); const fast_glob_1 = __importDefault(require("fast-glob")); const find_up_1 = __importDefault(require("find-up")); const fs_extra_1 = __importDefault(require("fs-extra")); const module_1 = require("module"); const path_1 = __importDefault(require("path")); const ExpoModuleConfig_1 = require("./ExpoModuleConfig"); // Names of the config files. From lowest to highest priority. const EXPO_MODULE_CONFIG_FILENAMES = ['unimodule.json', 'expo-module.config.json']; /** * Path to the `package.json` of the closest project in the current working dir. */ const projectPackageJsonPath = find_up_1.default.sync('package.json', { cwd: process.cwd() }); // This won't happen in usual scenarios, but we need to unwrap the optional path :) if (!projectPackageJsonPath) { throw new Error(`Couldn't find "package.json" up from path "${process.cwd()}"`); } /** * Custom `require` that resolves from the current working dir instead of this script path. * **Requires Node v12.2.0** */ const projectRequire = (0, module_1.createRequire)(projectPackageJsonPath); /** * Resolves autolinking search paths. If none is provided, it accumulates all node_modules when * going up through the path components. This makes workspaces work out-of-the-box without any configs. */ async function resolveSearchPathsAsync(searchPaths, cwd) { return searchPaths && searchPaths.length > 0 ? searchPaths.map((searchPath) => path_1.default.resolve(cwd, searchPath)) : await findDefaultPathsAsync(cwd); } exports.resolveSearchPathsAsync = resolveSearchPathsAsync; /** * Looks up for workspace's `node_modules` paths. */ async function findDefaultPathsAsync(cwd) { const paths = []; let dir = cwd; let pkgJsonPath; while ((pkgJsonPath = await (0, find_up_1.default)('package.json', { cwd: dir }))) { dir = path_1.default.dirname(path_1.default.dirname(pkgJsonPath)); paths.push(path_1.default.join(pkgJsonPath, '..', 'node_modules')); } return paths; } exports.findDefaultPathsAsync = findDefaultPathsAsync; /** * Searches for modules to link based on given config. */ async function findModulesAsync(providedOptions) { var _a, _b, _c; const options = await mergeLinkingOptionsAsync(providedOptions); const results = {}; for (const searchPath of options.searchPaths) { const bracedFilenames = '{' + EXPO_MODULE_CONFIG_FILENAMES.join(',') + '}'; const paths = await (0, fast_glob_1.default)([`*/${bracedFilenames}`, `@*/*/${bracedFilenames}`], { cwd: searchPath, }); // If the package has multiple configs (e.g. `unimodule.json` and `expo-module.config.json` during the transition time) // then we want to give `expo-module.config.json` the priority. const uniqueConfigPaths = Object.values(paths.reduce((acc, configPath) => { const dirname = path_1.default.dirname(configPath); if (!acc[dirname] || configPriority(configPath) > configPriority(acc[dirname])) { acc[dirname] = configPath; } return acc; }, {})); for (const packageConfigPath of uniqueConfigPaths) { const packagePath = await fs_extra_1.default.realpath(path_1.default.join(searchPath, path_1.default.dirname(packageConfigPath))); const expoModuleConfig = (0, ExpoModuleConfig_1.requireAndResolveExpoModuleConfig)(path_1.default.join(packagePath, path_1.default.basename(packageConfigPath))); const { name, version } = require(path_1.default.join(packagePath, 'package.json')); if (((_a = options.exclude) === null || _a === void 0 ? void 0 : _a.includes(name)) || !expoModuleConfig.supportsPlatform(options.platform)) { continue; } const currentRevision = { path: packagePath, version, }; if (!results[name]) { // The revision that was found first will be the main one. // An array of duplicates and the config are needed only here. results[name] = { ...currentRevision, config: expoModuleConfig, duplicates: [], }; } else if (results[name].path !== packagePath && ((_b = results[name].duplicates) === null || _b === void 0 ? void 0 : _b.every(({ path }) => path !== packagePath))) { (_c = results[name].duplicates) === null || _c === void 0 ? void 0 : _c.push(currentRevision); } } } // It doesn't make much sense to strip modules if there is only one search path. // Workspace root usually doesn't specify all its dependencies (see Expo Go), // so in this case we should link everything. if (options.searchPaths.length <= 1) { return results; } return filterToProjectDependencies(results, providedOptions); } exports.findModulesAsync = findModulesAsync; /** * Filters out packages that are not the dependencies of the project. */ function filterToProjectDependencies(results, options = {}) { const filteredResults = {}; const visitedPackages = new Set(); // Helper for traversing the dependency hierarchy. function visitPackage(packageJsonPath) { const packageJson = require(packageJsonPath); // Prevent getting into the recursive loop. if (visitedPackages.has(packageJson.name)) { return; } visitedPackages.add(packageJson.name); // Iterate over the dependencies to find transitive modules. for (const dependencyName in packageJson.dependencies) { const dependencyResult = results[dependencyName]; if (!filteredResults[dependencyName]) { let dependencyPackageJsonPath; if (dependencyResult) { filteredResults[dependencyName] = dependencyResult; dependencyPackageJsonPath = path_1.default.join(dependencyResult.path, 'package.json'); } else { try { dependencyPackageJsonPath = projectRequire.resolve(`${dependencyName}/package.json`); } catch (error) { // Some packages don't include package.json in its `exports` field, // but none of our packages do that, so it seems fine to just ignore that type of error. // Related issue: https://github.com/react-native-community/cli/issues/1168 if (!options.silent && error.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED') { console.warn(chalk_1.default.yellow(`⚠️ Cannot resolve the path to "${dependencyName}" package.`)); } continue; } } // Visit the dependency package. visitPackage(dependencyPackageJsonPath); } } } // Visit project's package. visitPackage(projectPackageJsonPath); return filteredResults; } /** * Merges autolinking options from different sources (the later the higher priority) * - options defined in package.json's `expoModules` field * - platform-specific options from the above (e.g. `expoModules.ios`) * - options provided to the CLI command */ async function mergeLinkingOptionsAsync(providedOptions) { var _a; const packageJson = require(projectPackageJsonPath); const baseOptions = (_a = packageJson.expo) === null || _a === void 0 ? void 0 : _a.autolinking; const platformOptions = providedOptions.platform && (baseOptions === null || baseOptions === void 0 ? void 0 : baseOptions[providedOptions.platform]); const finalOptions = Object.assign({}, baseOptions, platformOptions, providedOptions); // Makes provided paths absolute or falls back to default paths if none was provided. finalOptions.searchPaths = await resolveSearchPathsAsync(finalOptions.searchPaths, process.cwd()); return finalOptions; } exports.mergeLinkingOptionsAsync = mergeLinkingOptionsAsync; /** * Verifies the search results by checking whether there are no duplicates. */ function verifySearchResults(searchResults) { var _a; const cwd = process.cwd(); const relativePath = (pkg) => path_1.default.relative(cwd, pkg.path); let counter = 0; for (const moduleName in searchResults) { const revision = searchResults[moduleName]; if ((_a = revision.duplicates) === null || _a === void 0 ? void 0 : _a.length) { console.warn(`⚠️ Found multiple revisions of ${chalk_1.default.green(moduleName)}`); console.log(` - ${chalk_1.default.magenta(relativePath(revision))} (${chalk_1.default.cyan(revision.version)})`); for (const duplicate of revision.duplicates) { console.log(` - ${chalk_1.default.gray(relativePath(duplicate))} (${chalk_1.default.gray(duplicate.version)})`); } counter++; } } if (counter > 0) { console.warn('⚠️ Please get rid of multiple revisions as it may introduce some side effects or compatibility issues'); } return counter; } exports.verifySearchResults = verifySearchResults; /** * Resolves search results to a list of platform-specific configuration. */ async function resolveModulesAsync(searchResults, options) { const platformLinking = require(`./platforms/${options.platform}`); return (await Promise.all(Object.entries(searchResults).map(async ([packageName, revision]) => { const resolvedModule = await platformLinking.resolveModuleAsync(packageName, revision, options); return resolvedModule ? { packageName, packageVersion: revision.version, ...resolvedModule, } : null; }))) .filter(Boolean) .sort((a, b) => a.packageName.localeCompare(b.packageName)); } exports.resolveModulesAsync = resolveModulesAsync; /** * Generates a source file listing all packages to link. * Right know it works only for Android platform. */ async function generatePackageListAsync(modules, options) { try { const platformLinking = require(`./platforms/${options.platform}`); await platformLinking.generatePackageListAsync(modules, options.target, options.namespace); } catch (e) { console.error(chalk_1.default.red(`Generating package list is not available for platform: ${options.platform}`)); throw e; } } exports.generatePackageListAsync = generatePackageListAsync; /** * Returns the priority of the config at given path. Higher number means higher priority. */ function configPriority(fullpath) { return EXPO_MODULE_CONFIG_FILENAMES.indexOf(path_1.default.basename(fullpath)); } //# sourceMappingURL=autolinking.js.map