1import JsonFile from '@expo/json-file'; 2import chalk from 'chalk'; 3import resolveFrom from 'resolve-from'; 4 5import { getNativeModuleVersionsAsync } from '../../../api/getNativeModuleVersions'; 6import * as Log from '../../../log'; 7import { env } from '../../../utils/env'; 8import { CommandError } from '../../../utils/errors'; 9 10const debug = require('debug')( 11 'expo:doctor:dependencies:bundledNativeModules' 12) as typeof console.log; 13 14export type BundledNativeModules = Record<string, string>; 15 16/** 17 * Gets the bundledNativeModules.json for a given SDK version: 18 * - Tries to fetch the data from the /sdks/:sdkVersion/native-modules API endpoint. 19 * - If the data is missing on the server (it can happen for SDKs that are yet fully released) 20 * or there's a downtime, reads the local .json file from the "expo" package. 21 * - For UNVERSIONED, returns the local .json file contents. 22 */ 23export async function getVersionedNativeModulesAsync( 24 projectRoot: string, 25 sdkVersion: string 26): Promise<BundledNativeModules> { 27 if (sdkVersion !== 'UNVERSIONED' && !env.EXPO_OFFLINE) { 28 try { 29 debug('Fetching bundled native modules from the server...'); 30 return await getNativeModuleVersionsAsync(sdkVersion); 31 } catch (error: any) { 32 if (error instanceof CommandError && (error.code === 'OFFLINE' || error.code === 'API')) { 33 Log.warn( 34 chalk`Unable to reach well-known versions endpoint. Using local dependency map {bold expo/bundledNativeModules.json} for version validation` 35 ); 36 } else { 37 throw error; 38 } 39 } 40 } 41 42 debug('Fetching bundled native modules from the local JSON file...'); 43 return await getBundledNativeModulesAsync(projectRoot); 44} 45 46/** 47 * Get the legacy static `bundledNativeModules.json` file 48 * that's shipped with the version of `expo` that the project has installed. 49 */ 50async function getBundledNativeModulesAsync(projectRoot: string): Promise<BundledNativeModules> { 51 // TODO: Revisit now that this code is in the `expo` package. 52 const bundledNativeModulesPath = resolveFrom.silent( 53 projectRoot, 54 'expo/bundledNativeModules.json' 55 ); 56 if (!bundledNativeModulesPath) { 57 Log.log(); 58 throw new CommandError( 59 chalk`The dependency map {bold expo/bundledNativeModules.json} cannot be found, please ensure you have the package "{bold expo}" installed in your project.` 60 ); 61 } 62 return await JsonFile.readAsync<BundledNativeModules>(bundledNativeModulesPath); 63} 64