UNPKG

@nx/expo

Version:

The Expo Plugin for Nx contains executors and generators for managing and developing an expo application within your workspace. For example, you can directly build for different target platforms as well as generate projects and publish your code.

163 lines (162 loc) 6.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getResolveRequest = getResolveRequest; const tsconfig_paths_1 = require("tsconfig-paths"); const pc = require("picocolors"); const enhanced_resolve_1 = require("enhanced-resolve"); const path_1 = require("path"); const fs = require("fs"); const devkit_1 = require("@nx/devkit"); // Cache for metro-resolver module let metroResolver = null; /** * Lazily require metro-resolver to handle cases where it might not be installed */ function getMetroResolver() { if (!metroResolver) { try { metroResolver = require('metro-resolver'); } catch (error) { throw new Error('metro-resolver is required but not installed. Please install metro-resolver >= 0.82.0'); } } return metroResolver; } /* * Use tsconfig to resolve additional workspace libs. * * This resolve function requires projectRoot to be set to * workspace root in order modules and assets to be registered and watched. */ function getResolveRequest(extensions, exportsConditionNames = [], mainFields = []) { return function (_context, realModuleName, platform) { const debug = process.env.NX_REACT_NATIVE_DEBUG === 'true'; const { resolveRequest, ...context } = _context; const resolvedPath = resolveRequestFromContext(resolveRequest, _context, realModuleName, platform, debug) ?? defaultMetroResolver(context, realModuleName, platform, debug) ?? tsconfigPathsResolver(context, extensions, realModuleName, platform, debug) ?? pnpmResolver(extensions, context, realModuleName, debug, exportsConditionNames, mainFields); if (resolvedPath) { return resolvedPath; } if (debug) { console.log(pc.red(`[Nx] Unable to resolve with any resolver: ${realModuleName}`)); } throw new Error(`Cannot resolve ${pc.bold(realModuleName)}`); }; } function resolveRequestFromContext(resolveRequest, context, realModuleName, platform, debug) { try { return resolveRequest(context, realModuleName, platform); } catch { if (debug) console.log(pc.cyan(`[Nx] Unable to resolve with default resolveRequest: ${realModuleName}`)); } } /** * This function try to resolve path using metro's default resolver * @returns path if resolved, else undefined */ function defaultMetroResolver(context, realModuleName, platform, debug) { try { const resolver = getMetroResolver(); return resolver.resolve(context, realModuleName, platform); } catch { if (debug) console.log(pc.cyan(`[Nx] Unable to resolve with default Metro resolver: ${realModuleName}`)); } } /** * This resolver try to resolve module for pnpm. * @returns path if resolved, else undefined * This pnpm resolver is inspired from https://github.com/vjpr/pnpm-react-native-example/blob/main/packages/pnpm-expo-helper/util/make-resolver.js */ function pnpmResolver(extensions, context, realModuleName, debug, exportsConditionNames = [], mainFields = []) { try { const pnpmResolve = getPnpmResolver(extensions, exportsConditionNames, mainFields); const lookupStartPath = (0, path_1.dirname)(context.originModulePath); const filePath = pnpmResolve.resolveSync({}, lookupStartPath, realModuleName); if (filePath) { return { type: 'sourceFile', filePath }; } } catch { if (debug) console.log(pc.cyan(`[Nx] Unable to resolve with default PNPM resolver: ${realModuleName}`)); } } /** * This function try to resolve files that are specified in tsconfig's paths * @returns path if resolved, else undefined */ function tsconfigPathsResolver(context, extensions, realModuleName, platform, debug) { try { const tsConfigPathMatcher = getMatcher(debug); const match = tsConfigPathMatcher(realModuleName, undefined, undefined, extensions.map((ext) => `.${ext}`)); const resolver = getMetroResolver(); return resolver.resolve(context, match, platform); } catch { if (debug) { console.log(pc.cyan(`[Nx] Failed to resolve ${pc.bold(realModuleName)}`)); console.log(pc.cyan(`[Nx] The following tsconfig paths was used:\n:${pc.bold(JSON.stringify(paths, null, 2))}`)); } } } let matcher; let absoluteBaseUrl; let paths; function getMatcher(debug) { if (!matcher) { const result = (0, tsconfig_paths_1.loadConfig)(); if (result.resultType === 'success') { absoluteBaseUrl = result.absoluteBaseUrl; paths = result.paths; if (debug) { console.log(pc.cyan(`[Nx] Located tsconfig at ${pc.bold(absoluteBaseUrl)}`)); console.log(pc.cyan(`[Nx] Found the following paths:\n:${pc.bold(JSON.stringify(paths, null, 2))}`)); } matcher = (0, tsconfig_paths_1.createMatchPath)(absoluteBaseUrl, paths); } else { console.log(pc.cyan(`[Nx] Failed to locate tsconfig}`)); throw new Error(`Could not load tsconfig for project`); } } return matcher; } /** * This function returns resolver for pnpm. * It is inspired form https://github.com/vjpr/pnpm-expo-example/blob/main/packages/pnpm-expo-helper/util/make-resolver.js. */ let pnpmpResolver; function getPnpmResolver(extensions, exportsConditionNames = [], mainFields = []) { if (!pnpmpResolver) { // Create a filesystem adapter that matches enhanced-resolve's expected interface // The issue is that Node.js fs types allow withFileTypes: true, but enhanced-resolve expects withFileTypes?: false // This is compatible with the latest version of enhanced-resolve and is the intended way to use it. // See https://github.com/webpack/enhanced-resolve/commit/d55471f20c17bce4def0b53cfe0b7027e7b48d82 const fileSystem = new enhanced_resolve_1.CachedInputFileSystem(fs, 4000); pnpmpResolver = enhanced_resolve_1.ResolverFactory.createResolver({ fileSystem, extensions: extensions.map((extension) => '.' + extension), useSyncFileSystemCalls: true, modules: [(0, path_1.join)(devkit_1.workspaceRoot, 'node_modules'), 'node_modules'], conditionNames: [ 'native', 'browser', 'require', 'default', 'react-native', 'node', ...exportsConditionNames, ], mainFields: ['react-native', 'browser', 'main', ...mainFields], aliasFields: ['browser'], }); } return pnpmpResolver; }