CocoaPods integration for iOS and macOS projects with automatic CLI installation, intelligent error handling, and project detection.
Main class for managing CocoaPods operations in iOS/macOS projects.
class CocoaPodsPackageManager {
readonly name = 'CocoaPods';
constructor(options: { cwd: string; silent?: boolean });
/** Runs `pod install` and attempts to automatically run known troubleshooting steps */
installAsync(options?: { spinner?: Ora }): Promise<void>;
/** Check if CocoaPods CLI is installed */
isCLIInstalledAsync(): Promise<boolean>;
/** Install CocoaPods CLI non-interactively */
installCLIAsync(): Promise<boolean>;
/** Get CocoaPods version */
versionAsync(): Promise<string>;
/** Handle pod install errors with automatic remediation */
handleInstallErrorAsync(options: {
error: any;
spinner?: Ora;
shouldUpdate?: boolean;
updatedPackages?: string[];
}): Promise<SpawnResult>;
}Usage Examples:
import { CocoaPodsPackageManager } from '@expo/package-manager';
const podManager = new CocoaPodsPackageManager({
cwd: '/path/to/ios/project',
silent: false
});
// Install pods with automatic error handling
await podManager.installAsync();
// Check CLI status
const hasCocoaPods = await podManager.isCLIInstalledAsync();
if (!hasCocoaPods) {
await podManager.installCLIAsync();
}Class methods for project detection and CLI installation.
class CocoaPodsPackageManager {
/** Find the iOS/macOS project root containing a Podfile */
static getPodProjectRoot(projectRoot: string): string | null;
/** Check if a project uses CocoaPods */
static isUsingPods(projectRoot: string): boolean;
/** Check if CocoaPods CLI is available in the system */
static isCLIInstalledAsync(spawnOptions?: SpawnOptions): Promise<boolean>;
/** Check if CocoaPods is available for the current platform and project */
static isAvailable(projectRoot: string, silent: boolean): boolean;
/** Install CocoaPods CLI automatically using multiple methods */
static installCLIAsync(options: {
nonInteractive?: boolean;
spawnOptions?: SpawnOptions;
}): Promise<boolean>;
/** Install CocoaPods CLI using gem */
static gemInstallCLIAsync(
nonInteractive?: boolean,
spawnOptions?: SpawnOptions
): Promise<void>;
/** Install CocoaPods CLI using Homebrew */
static brewInstallCLIAsync(spawnOptions?: SpawnOptions): Promise<void>;
/** Link CocoaPods CLI using Homebrew */
static brewLinkCLIAsync(spawnOptions?: SpawnOptions): Promise<void>;
}Usage Examples:
// Project detection
const iosRoot = CocoaPodsPackageManager.getPodProjectRoot('/path/to/project');
const usesPods = CocoaPodsPackageManager.isUsingPods('/path/to/ios');
// Platform and availability checking
const available = CocoaPodsPackageManager.isAvailable('/path/to/project', false);
// CLI installation
if (!await CocoaPodsPackageManager.isCLIInstalledAsync()) {
await CocoaPodsPackageManager.installCLIAsync({
nonInteractive: true
});
}
// Manual installation methods
try {
await CocoaPodsPackageManager.gemInstallCLIAsync(true);
} catch (error) {
await CocoaPodsPackageManager.brewInstallCLIAsync();
}CocoaPods-specific error types and handling utilities.
type CocoaPodsErrorCode = 'NON_INTERACTIVE' | 'NO_CLI' | 'COMMAND_FAILED';
class CocoaPodsError extends Error {
readonly name = 'CocoaPodsError';
readonly isPackageManagerError = true;
constructor(
message: string,
public code: CocoaPodsErrorCode,
public cause?: Error
);
}
/** Extract missing dependency information from CocoaPods error output */
function extractMissingDependencyError(errorOutput: string): [string, string] | null;
/** Parse pod update messages from error output */
function getPodUpdateMessage(output: string): {
updatePackage: string | null;
shouldUpdateRepo: boolean;
};
/** Format CocoaPods repo update messages with helpful context */
function getPodRepoUpdateMessage(errorOutput: string): {
message: string;
updatePackage?: string;
shouldUpdateRepo?: boolean;
};
/** Format CocoaPods install errors with improved messaging and troubleshooting */
function getImprovedPodInstallError(
error: SpawnResult & Error,
options: { cwd?: string }
): Error;Usage Examples:
import {
CocoaPodsError,
extractMissingDependencyError,
getImprovedPodInstallError
} from '@expo/package-manager';
try {
await podManager.installAsync();
} catch (error) {
if (error instanceof CocoaPodsError) {
switch (error.code) {
case 'NO_CLI':
console.log('CocoaPods CLI not installed');
break;
case 'COMMAND_FAILED':
console.log('Pod command failed:', error.message);
break;
}
}
}
// Parse error information
const errorOutput = "Unable to find a specification for `expo-camera` depended upon by `expo-app`";
const [missing, dependent] = extractMissingDependencyError(errorOutput);
// missing: "expo-camera", dependent: "expo-app"The CocoaPods manager includes intelligent error handling and automatic remediation:
Automatic Repo Updates:
// Automatically detects when `pod install --repo-update` is needed
await podManager.installAsync(); // May internally run repo update if neededMissing Dependency Resolution:
// Automatically attempts to resolve missing dependencies
// by updating specific packages or running repo updates
try {
await podManager.installAsync();
} catch (error) {
// Error handling includes specific remediation steps
const improvedError = getImprovedPodInstallError(error, { cwd: projectRoot });
console.log(improvedError.message); // Contains helpful troubleshooting steps
}CLI Installation Fallbacks:
// Tries multiple installation methods automatically
await CocoaPodsPackageManager.installCLIAsync({
nonInteractive: true
});
// 1. Attempts gem install
// 2. Falls back to brew install
// 3. Attempts brew link if needed
// 4. Provides clear error messages if all methods failCocoaPods manager can detect iOS/macOS projects in different locations:
// Checks multiple possible locations:
// 1. projectRoot/Podfile (direct)
// 2. projectRoot/ios/Podfile (React Native style)
// 3. projectRoot/macos/Podfile (macOS projects)
const podRoot = CocoaPodsPackageManager.getPodProjectRoot('/path/to/project');
if (podRoot) {
const podManager = new CocoaPodsPackageManager({ cwd: podRoot });
await podManager.installAsync();
}CocoaPods is macOS-only and requires proper platform detection:
// Automatically checks platform and project compatibility
const available = CocoaPodsPackageManager.isAvailable(projectRoot, false);
// Returns false if:
// - Not running on macOS
// - No Podfile found in project or ios/macos subdirectories