Provides comprehensive access to the local file system on mobile devices through Expo's module system.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Access to system directories (cache, document, bundle) and comprehensive path manipulation utilities with cross-platform compatibility and Apple shared container support.
Provides access to system directories and path manipulation utilities, extending PathUtilities with system-specific functionality.
/**
* Provides access to system directories and path utilities
*/
class Paths extends PathUtilities {
/** Cache directory - files can be deleted by system when storage is low */
static get cache(): Directory;
/** Bundle directory - contains app assets and resources */
static get bundle(): Directory;
/** Document directory - persistent storage safe from system deletion */
static get document(): Directory;
/** Apple shared containers for app groups (iOS only) */
static get appleSharedContainers(): Record<string, Directory>;
/** Total disk space on device in bytes */
static get totalDiskSpace(): number;
/** Available disk space on device in bytes */
static get availableDiskSpace(): number;
/** Returns path information for specified path segments */
static info(...uris: string[]): PathInfo;
}Access platform-specific directories with appropriate permissions and usage patterns.
/**
* Cache directory - temporary storage that can be cleared by system
* Use for downloaded files, generated thumbnails, and temporary data
*/
static get cache(): Directory;
/**
* Document directory - persistent user data storage
* Use for user-created files, app data, and important documents
*/
static get document(): Directory;
/**
* Bundle directory - read-only app resources and assets
* Contains files bundled with the application during build
*/
static get bundle(): Directory;
/**
* Apple shared containers for app group access (iOS only)
* Provides access to shared storage between apps in the same app group
*/
static get appleSharedContainers(): Record<string, Directory>;Usage Examples:
import { Paths } from "expo-file-system";
// Cache directory usage - temporary files
const tempFile = Paths.cache.createFile("temp-download.zip", "application/zip");
tempFile.write(downloadedData);
console.log(`Cached file at: ${tempFile.uri}`);
// Document directory usage - persistent storage
const userDocument = Paths.document.createFile("user-data.json", "application/json");
userDocument.write(JSON.stringify(userData));
// Bundle directory usage - read app assets
const configFile = new File(Paths.bundle, "config.json");
if (configFile.exists) {
const config = JSON.parse(await configFile.text());
console.log("App configuration:", config);
}
// Apple shared containers (iOS only)
const sharedContainers = Paths.appleSharedContainers;
Object.keys(sharedContainers).forEach(appGroupId => {
const containerDir = sharedContainers[appGroupId];
console.log(`App group ${appGroupId}: ${containerDir.uri}`);
});Monitor device storage space for intelligent caching and storage management.
/**
* Total disk space on the device's internal storage in bytes
*/
static get totalDiskSpace(): number;
/**
* Available disk space on the device's internal storage in bytes
*/
static get availableDiskSpace(): number;Usage Examples:
import { Paths } from "expo-file-system";
// Check available storage
const totalSpace = Paths.totalDiskSpace;
const availableSpace = Paths.availableDiskSpace;
const usedSpace = totalSpace - availableSpace;
console.log(`Total storage: ${(totalSpace / 1024 / 1024 / 1024).toFixed(2)} GB`);
console.log(`Available: ${(availableSpace / 1024 / 1024 / 1024).toFixed(2)} GB`);
console.log(`Used: ${(usedSpace / 1024 / 1024 / 1024).toFixed(2)} GB`);
// Storage management logic
const MINIMUM_FREE_SPACE = 100 * 1024 * 1024; // 100 MB
if (availableSpace < MINIMUM_FREE_SPACE) {
console.warn("Low storage space - cleaning cache...");
// Clear cache directory
const cacheContents = Paths.cache.list();
for (const item of cacheContents) {
if (item instanceof File) {
item.delete();
}
}
}
// Progressive quality based on storage
const storageRatio = availableSpace / totalSpace;
const imageQuality = storageRatio > 0.5 ? 'high' : storageRatio > 0.2 ? 'medium' : 'low';
console.log(`Using ${imageQuality} quality images based on available storage`);Query path existence and type information for any filesystem path.
/**
* Returns information about specified path(s)
* @param uris Path segments to join and query
* @returns PathInfo with existence and type information
*/
static info(...uris: string[]): PathInfo;
interface PathInfo {
/** Whether the path exists and is accessible */
exists: boolean;
/** Whether the path is a directory, null if path doesn't exist */
isDirectory: boolean | null;
}Usage Examples:
import { Paths } from "expo-file-system";
// Check if path exists and get type
const pathInfo = Paths.info("/data/user/documents/myfile.txt");
console.log(`Path exists: ${pathInfo.exists}`);
if (pathInfo.exists) {
console.log(`Is directory: ${pathInfo.isDirectory}`);
}
// Check multiple path segments
const nestedInfo = Paths.info("documents", "projects", "app");
if (nestedInfo.exists && nestedInfo.isDirectory) {
console.log("Project directory exists");
}
// Validate paths before operations
function safePathOperation(pathSegments: string[]) {
const info = Paths.info(...pathSegments);
if (!info.exists) {
throw new Error("Path does not exist");
}
if (info.isDirectory === null) {
throw new Error("Cannot determine path type");
}
return info.isDirectory ? "directory" : "file";
}Comprehensive path manipulation utilities inherited by the Paths class.
/**
* Joins path segments into a single path with proper URL encoding
* @param paths Array of path segments, File instances, or Directory instances
* @returns Joined path string
*/
static join(...paths: (string | File | Directory)[]): string;
/**
* Calculates relative path between two paths
* @param from Base path
* @param to Target path
* @returns Relative path string
*/
static relative(from: string | File | Directory, to: string | File | Directory): string;
/**
* Checks if a path is absolute
* @param path Path to check
* @returns True if path is absolute
*/
static isAbsolute(path: string | File | Directory): boolean;
/**
* Normalizes a path by resolving . and .. segments
* @param path Path to normalize
* @returns Normalized path string
*/
static normalize(path: string | File | Directory): string;
/**
* Returns the directory portion of a path
* @param path Path to process
* @returns Directory path string
*/
static dirname(path: string | File | Directory): string;
/**
* Returns the filename portion of a path
* @param path Path to process
* @param ext Optional extension to remove
* @returns Filename string
*/
static basename(path: string | File | Directory, ext?: string): string;
/**
* Returns the extension portion of a path
* @param path Path to process
* @returns Extension string including the dot
*/
static extname(path: string | File | Directory): string;
/**
* Parses a path into its component parts
* @param path Path to parse
* @returns Object with path components
*/
static parse(path: string | File | Directory): {
root: string;
dir: string;
base: string;
ext: string;
name: string;
};Usage Examples:
import { Paths, File, Directory } from "expo-file-system";
// Path joining with mixed types
const docDir = Paths.document;
const projectFile = new File(docDir, "projects", "app.json");
const configPath = Paths.join(docDir, "config", "settings.json");
console.log(`Config path: ${configPath}`);
// Relative path calculation
const relativePath = Paths.relative(
Paths.document.uri,
Paths.join(Paths.document, "subfolder", "file.txt")
);
console.log(`Relative path: ${relativePath}`);
// Path validation and normalization
const messyPath = "/documents/../documents/./files//data.txt";
const cleanPath = Paths.normalize(messyPath);
console.log(`Normalized: ${cleanPath}`);
// Path component extraction
const filePath = "/documents/projects/mobile-app/src/index.ts";
const parsed = Paths.parse(filePath);
console.log(`Directory: ${parsed.dir}`);
console.log(`Filename: ${parsed.name}`);
console.log(`Extension: ${parsed.ext}`);
// Cross-platform absolute path checking
const paths = [
"/absolute/unix/path",
"relative/path",
"file:///absolute/file/uri",
"C:\\Windows\\Path"
];
paths.forEach(path => {
console.log(`${path} is absolute: ${Paths.isAbsolute(path)}`);
});
// Safe filename extraction
function getFileInfo(path: string) {
const basename = Paths.basename(path);
const extension = Paths.extname(path);
const nameWithoutExt = Paths.basename(path, extension);
return {
fullname: basename,
name: nameWithoutExt,
extension: extension,
directory: Paths.dirname(path)
};
}
const fileInfo = getFileInfo("/documents/photos/vacation-2024.png");
console.log(fileInfo);
// Output: {
// fullname: "vacation-2024.png",
// name: "vacation-2024",
// extension: ".png",
// directory: "/documents/photos"
// }Handle platform differences and specialized directory access patterns.
Usage Examples:
import { Paths, Directory } from "expo-file-system";
import { Platform } from "react-native";
// Platform-specific directory setup
function setupAppDirectories() {
const appDataDir = Paths.document.createDirectory("AppData");
const cacheDir = Paths.cache.createDirectory("AppCache");
// iOS-specific shared container access
if (Platform.OS === 'ios') {
const sharedContainers = Paths.appleSharedContainers;
// Access shared container for app group
const appGroupId = "group.com.company.myapp";
if (sharedContainers[appGroupId]) {
const sharedDir = sharedContainers[appGroupId];
const sharedData = sharedDir.createFile("shared-config.json", "application/json");
console.log(`Shared data location: ${sharedData.uri}`);
}
}
return { appDataDir, cacheDir };
}
// Intelligent storage location selection
function selectStorageLocation(fileType: string, fileSize: number): Directory {
const availableSpace = Paths.availableDiskSpace;
const isLargeFile = fileSize > 10 * 1024 * 1024; // 10MB
const hasLowStorage = availableSpace < 100 * 1024 * 1024; // 100MB
// Use cache for large files when storage is limited
if (isLargeFile && hasLowStorage) {
console.log("Using cache directory due to storage constraints");
return Paths.cache;
}
// Use documents for important file types
const importantTypes = ['.json', '.xml', '.config', '.db'];
if (importantTypes.some(type => fileType.includes(type))) {
return Paths.document;
}
// Default to cache for temporary files
return Paths.cache;
}
// Storage monitoring and cleanup
function monitorStorage() {
const totalSpace = Paths.totalDiskSpace;
const availableSpace = Paths.availableDiskSpace;
const usagePercent = ((totalSpace - availableSpace) / totalSpace) * 100;
console.log(`Storage usage: ${usagePercent.toFixed(1)}%`);
// Cleanup strategy based on usage
if (usagePercent > 90) {
console.log("Critical storage - aggressive cleanup");
cleanupOldCacheFiles(7); // Clean files older than 7 days
} else if (usagePercent > 80) {
console.log("High storage usage - moderate cleanup");
cleanupOldCacheFiles(30); // Clean files older than 30 days
}
}
function cleanupOldCacheFiles(daysOld: number) {
const cutoffTime = Date.now() - (daysOld * 24 * 60 * 60 * 1000);
const cacheContents = Paths.cache.list();
cacheContents.forEach(item => {
if (item instanceof File && item.modificationTime) {
if (item.modificationTime < cutoffTime) {
console.log(`Cleaning up old cache file: ${item.name}`);
item.delete();
}
}
});
}