Core functionality for reading, parsing, and modifying Expo project configurations. Supports both static (JSON) and dynamic (JavaScript/TypeScript) configuration files with plugin integration and validation.
Read and evaluate the complete configuration for an Expo project.
/**
* Evaluate the config for an Expo project.
* Supports app.config.js/ts (dynamic) and app.json/app.config.json (static)
* @param projectRoot - Root folder containing application code
* @param options - Configuration options for reading
* @returns Complete project configuration with defaults applied
*/
function getConfig(projectRoot: string, options?: GetConfigOptions): ProjectConfig;
interface GetConfigOptions {
/** Return only public-facing options, omitting private keys */
isPublicConfig?: boolean;
/** Preserve config mods for compilation (used in eject command) */
isModdedConfig?: boolean;
/** Skip SDK version requirement validation */
skipSDKVersionRequirement?: boolean;
/** Skip resolving plugins */
skipPlugins?: boolean;
/** Enable strict validation */
strict?: boolean;
}
interface ProjectConfig {
/** Fully evaluated Expo config with default values injected */
exp: ExpoConfig;
/** Dynamic config for processing native files during generation */
mods?: ModConfig | null;
/** Project package.json object with default values injected */
pkg: PackageJSONConfig;
/** Unaltered static config (app.config.json, app.json, or custom) */
rootConfig: AppJSONConfig;
/** Path to static json config file if it exists */
staticConfigPath: string | null;
/** Path to app.config.js or app.config.ts if it exists */
dynamicConfigPath: string | null;
/** Type of value exported from dynamic config ('function' | 'object' | null) */
dynamicConfigObjectType: string | null;
/** True if both static and dynamic configs exist with potential conflicts */
hasUnusedStaticConfig: boolean;
}Usage Examples:
import { getConfig } from "@expo/config";
// Basic configuration reading
const config = getConfig("/path/to/expo-project");
console.log("App name:", config.exp.name);
console.log("Platforms:", config.exp.platforms);
// Public config only (safe for hosting)
const publicConfig = getConfig("/path/to/expo-project", {
isPublicConfig: true
});
// privateKeys, _internal, etc. are removed
// Skip SDK version requirement for incomplete projects
const configWithoutSDK = getConfig("/path/to/expo-project", {
skipSDKVersionRequirement: true
});Read the package.json file with default values applied.
/**
* Read package.json for an Expo project with defaults applied
* @param projectRoot - Root folder containing package.json
* @returns Package.json content with name and version defaults
*/
function getPackageJson(projectRoot: string): PackageJSONConfig;
interface PackageJSONConfig {
dependencies?: Record<string, string>;
[key: string]: any;
}Get the paths to static and dynamic configuration files.
/**
* Get the static and dynamic config paths for a project
* @param projectRoot - Project root directory
* @returns Object containing paths to config files
*/
function getConfigFilePaths(projectRoot: string): ConfigFilePaths;
interface ConfigFilePaths {
/** Path to app.json or app.config.json */
staticConfigPath: string | null;
/** Path to app.config.js or app.config.ts */
dynamicConfigPath: string | null;
}Attempt to modify an Expo project configuration programmatically.
/**
* Attempt to modify an Expo project config.
* Only works fully with static configs. Dynamic configs return warnings.
* @param projectRoot - Project root directory
* @param modifications - Partial config changes to apply
* @param readOptions - Options for reading current config
* @param writeOptions - Options for writing config
* @returns Result indicating success, warning, or failure
*/
function modifyConfigAsync(
projectRoot: string,
modifications: Partial<ExpoConfig>,
readOptions?: GetConfigOptions,
writeOptions?: WriteConfigOptions
): Promise<{
type: 'success' | 'warn' | 'fail';
message?: string;
config: ExpoConfig | null;
}>;
interface WriteConfigOptions {
/** If true, changes are validated but not written */
dryRun?: boolean;
}Usage Examples:
import { modifyConfigAsync } from "@expo/config";
// Modify app name and version
const result = await modifyConfigAsync("/path/to/project", {
name: "New App Name",
version: "2.0.0"
});
if (result.type === 'success') {
console.log("Config updated successfully");
} else {
console.log("Warning:", result.message);
}
// Dry run to test changes
const dryResult = await modifyConfigAsync(
"/path/to/project",
{ name: "Test Name" },
{},
{ dryRun: true }
);Helper functions for extracting information from configurations.
/**
* Get web build output path from configuration
* @param config - Configuration object (optional)
* @returns Web build output directory path
*/
function getWebOutputPath(config?: { [key: string]: any }): string;
/**
* Extract app and web names from configuration
* @param exp - Configuration object
* @returns Object with appName and webName properties
*/
function getNameFromConfig(exp?: Record<string, any>): {
appName?: string;
webName?: string;
};
/**
* Determine if project uses managed or bare workflow
* @param projectRoot - Project root directory
* @param exp - Optional config to check SDK version
* @returns 'managed' or 'bare'
*/
function getDefaultTarget(
projectRoot: string,
exp?: Pick<ExpoConfig, 'sdkVersion'>
): ProjectTarget;
/**
* Get descriptive name of project config type
* @param projectRoot - Project root directory
* @returns Human-readable config description
*/
function getProjectConfigDescription(projectRoot: string): string;
/**
* Get config description with specific paths
* @param projectRoot - Project root directory
* @param projectConfig - Config file paths
* @returns Human-readable config description
*/
function getProjectConfigDescriptionWithPaths(
projectRoot: string,
projectConfig: ConfigFilePaths
): string;// Main configuration interface (extensive, showing key properties)
interface ExpoConfig {
name?: string;
slug?: string;
version?: string;
sdkVersion?: string;
platforms?: Platform[];
description?: string;
privacy?: 'public' | 'unlisted';
primaryColor?: string;
backgroundColor?: string;
// Platform-specific configurations
ios?: {
bundleIdentifier?: string;
buildNumber?: string;
config?: any;
// ... many more iOS-specific options
};
android?: {
package?: string;
versionCode?: number;
config?: any;
// ... many more Android-specific options
};
web?: {
build?: {
output?: string;
};
name?: string;
// ... web-specific options
};
// Plugin and build configuration
plugins?: any[];
hooks?: Hook[];
// Updates configuration
updates?: {
enabled?: boolean;
fallbackToCacheTimeout?: number;
codeSigningCertificate?: string;
codeSigningMetadata?: any;
// ... updates options
};
// Internal properties (removed in public configs)
_internal?: {
projectRoot?: string;
dynamicConfigPath?: string;
staticConfigPath?: string;
packageJsonPath?: string;
};
}
interface AppJSONConfig {
expo: ExpoConfig;
[key: string]: any;
}
// Context for dynamic configuration evaluation
interface ConfigContext {
projectRoot: string;
staticConfigPath: string | null;
packageJsonPath: string | null;
config: Partial<ExpoConfig>;
}
// Hook system types
interface Hook {
file: string;
config: any;
}
type HookType = 'postPublish' | 'postExport';
interface HookArguments {
config: any;
url: any;
exp: ExpoConfig;
iosBundle: string | Uint8Array;
iosSourceMap: string | null;
iosManifest: any;
iosManifestUrl: string;
androidBundle: string | Uint8Array;
androidSourceMap: string | null;
androidManifest: any;
androidManifestUrl: string;
projectRoot: string;
log: (msg: any) => void;
}
// Project privacy settings
enum ProjectPrivacy {
PUBLIC = 'public',
UNLISTED = 'unlisted'
}