Advanced dependency resolution system with caching, workspace support, and duplicate detection for efficient module management in React Native and Expo projects.
Main interface for cached dependency operations with platform-specific configuration loading.
/**
* Create a cached dependencies linker for efficient dependency management
* @param params - Configuration parameters including project root
* @returns CachedDependenciesLinker instance
*/
function makeCachedDependenciesLinker(params: {
projectRoot: string;
}): CachedDependenciesLinker;
interface CachedDependenciesLinker {
/** Get platform-specific search options and exclusions */
getOptionsForPlatform(platform: SupportedPlatform): Promise<CachedDependenciesSearchOptions>;
/** Load React Native project configuration */
loadReactNativeProjectConfig(): Promise<RNConfigReactNativeProjectConfig | null>;
/** Scan dependencies from React Native project config */
scanDependenciesFromRNProjectConfig(): Promise<ResolutionResult>;
/** Scan dependencies recursively from project */
scanDependenciesRecursively(): Promise<ResolutionResult>;
/** Scan dependencies in specific search path */
scanDependenciesInSearchPath(searchPath: string): Promise<ResolutionResult>;
}
interface CachedDependenciesSearchOptions {
excludeNames: Set<string>;
searchPaths: string[];
}Usage Examples:
import { makeCachedDependenciesLinker } from "expo-modules-autolinking";
// Create dependency linker
const linker = makeCachedDependenciesLinker({
projectRoot: "/path/to/project"
});
// Get platform-specific options
const iosOptions = await linker.getOptionsForPlatform("ios");
console.log("iOS search paths:", iosOptions.searchPaths);
console.log("iOS exclusions:", Array.from(iosOptions.excludeNames));
// Scan dependencies recursively
const dependencies = await linker.scanDependenciesRecursively();
console.log("Found dependencies:", Object.keys(dependencies));Core functions for scanning and resolving dependencies from various sources.
/**
* Scan dependencies recursively from project root
* @param rawPath - Root directory path to scan from
* @param options - Resolution configuration options
* @returns Promise resolving to dependency resolution results
*/
function scanDependenciesRecursively(
rawPath: string,
options?: {
shouldIncludeDependency?: (name: string) => boolean;
limitDepth?: number;
}
): Promise<ResolutionResult>;
/**
* Scan dependencies in specific search path
* @param rawPath - Directory path to scan
* @param options - Resolution configuration options
* @returns Promise resolving to dependency resolution results
*/
function scanDependenciesInSearchPath(
rawPath: string,
options?: {
shouldIncludeDependency?: (name: string) => boolean;
}
): Promise<ResolutionResult>;
/**
* Scan dependencies from React Native project configuration
* @param rawPath - Project root path
* @param projectConfig - React Native project configuration (can be null)
* @param options - Resolution configuration options
* @returns Promise resolving to dependency resolution results
*/
function scanDependenciesFromRNProjectConfig(
rawPath: string,
projectConfig: RNConfigReactNativeProjectConfig | null,
options?: {
shouldIncludeDependency?: (name: string) => boolean;
}
): Promise<ResolutionResult>;Usage Examples:
import {
scanDependenciesRecursively,
scanDependenciesInSearchPath,
scanDependenciesFromRNProjectConfig
} from "expo-modules-autolinking";
// Scan dependencies recursively
const allDeps = await scanDependenciesRecursively("/path/to/project", {
shouldIncludeDependency: (name) => !name.includes("react-native-vector-icons"),
limitDepth: 5
});
// Scan specific search path
const customDeps = await scanDependenciesInSearchPath("./custom-modules", {
shouldIncludeDependency: (name) => !name.startsWith("@types/")
});
// Scan from React Native config
const rnConfig = await loadReactNativeConfig();
const configDeps = await scanDependenciesFromRNProjectConfig(
"/path/to/project",
rnConfig,
{
shouldIncludeDependency: (name) => true
}
);Utility functions for processing and merging dependency resolution results.
/**
* Filter and map resolution results based on criteria
* @param result - Resolution result to filter
* @param filterFn - Function to filter dependencies
* @param mapFn - Function to transform dependency resolutions
* @returns Filtered and mapped resolution result
*/
function filterMapResolutionResult<T>(
result: ResolutionResult,
filterFn: (dep: DependencyResolution) => boolean,
mapFn: (dep: DependencyResolution) => T
): Record<string, T>;
/**
* Merge multiple resolution results into single result
* @param results - Array of resolution results to merge
* @returns Merged resolution result with conflict resolution
*/
function mergeResolutionResults(
...results: ResolutionResult[]
): ResolutionResult;Usage Examples:
import {
filterMapResolutionResult,
mergeResolutionResults
} from "expo-modules-autolinking";
// Filter to only production dependencies
const prodDeps = filterMapResolutionResult(
allDependencies,
(dep) => dep.source !== DependencyResolutionSource.SEARCH_PATH,
(dep) => ({ name: dep.name, version: dep.version })
);
// Merge results from multiple sources
const mergedDeps = mergeResolutionResults(
recursiveDeps,
searchPathDeps,
rnConfigDeps
);Functions for scanning Expo module resolutions with platform-specific filtering.
/**
* Scan dependency resolutions for specific platform
* @param platform - Target platform for scanning
* @param projectRoot - Project root directory
* @param options - Platform-specific scanning options
* @returns Promise resolving to platform-filtered resolution results
*/
function scanDependencyResolutionsForPlatform(
platform: SupportedPlatform,
projectRoot: string,
options?: PlatformScanOptions
): Promise<ResolutionResult>;
/**
* Scan Expo module resolutions for specific platform
* @param platform - Target platform for scanning
* @param projectRoot - Project root directory
* @param options - Expo module scanning options
* @returns Promise resolving to Expo module resolution results
*/
function scanExpoModuleResolutionsForPlatform(
platform: SupportedPlatform,
projectRoot: string,
options?: ExpoModuleScanOptions
): Promise<ResolutionResult>;Usage Examples:
import {
scanDependencyResolutionsForPlatform,
scanExpoModuleResolutionsForPlatform
} from "expo-modules-autolinking";
// Scan dependencies for iOS platform
const iosDeps = await scanDependencyResolutionsForPlatform("ios", "/path/to/project", {
excludeDevDependencies: true,
includeOptionalDependencies: false
});
// Scan only Expo modules for Android
const androidExpoModules = await scanExpoModuleResolutionsForPlatform("android", "/path/to/project");const enum DependencyResolutionSource {
RECURSIVE_RESOLUTION,
SEARCH_PATH,
RN_CLI_LOCAL,
}
interface BaseDependencyResolution {
name: string;
version: string;
path: string;
originPath: string;
}
interface DependencyResolution extends BaseDependencyResolution {
source: DependencyResolutionSource;
duplicates: BaseDependencyResolution[] | null;
depth: number;
[prop: string]: unknown;
}
type ResolutionResult = Record<string, DependencyResolution | undefined>;interface DependencyScanOptions {
excludeNames?: Set<string>;
maxDepth?: number;
includeDevDependencies?: boolean;
includeOptionalDependencies?: boolean;
}
interface PlatformScanOptions extends DependencyScanOptions {
platformSpecific?: boolean;
includeNativeModules?: boolean;
}
interface ExpoModuleScanOptions extends PlatformScanOptions {
requireExpoModuleConfig?: boolean;
includeLegacyModules?: boolean;
}The dependency management system includes sophisticated caching mechanisms:
Caching Example:
import { makeCachedDependenciesLinker } from "expo-modules-autolinking";
// Create linker with caching enabled
const linker = makeCachedDependenciesLinker({
projectRoot: "/path/to/monorepo",
});
// First scan - builds cache
const initialScan = await linker.scanDependenciesRecursively();
// Subsequent scans use cached results
const cachedScan = await linker.scanDependenciesRecursively();The dependency management system provides comprehensive error handling:
try {
const linker = makeCachedDependenciesLinker({
projectRoot: "/invalid/path"
});
const deps = await linker.scanDependenciesRecursively();
} catch (error) {
if (error instanceof ProjectNotFoundError) {
console.error("Project root not found:", error.path);
} else if (error instanceof DependencyResolutionError) {
console.error("Failed to resolve dependency:", error.packageName);
console.error("Reason:", error.reason);
}
}The dependency management system integrates seamlessly with native build systems: