File system crawling, watching and mapping library designed for Metro bundler ecosystem
tessl install tessl/npm-metro-file-map@0.83.0Metro File Map is an experimental file system crawling, watching and mapping library designed specifically for the Metro bundler ecosystem. Originally forked from jest-haste-map, it provides comprehensive file system operations including directory traversal, file change monitoring, and mapping capabilities essential for JavaScript bundling workflows.
npm install metro-file-mapimport FileMap, { DiskCacheManager, HastePlugin } from "metro-file-map";For CommonJS:
const FileMap = require("metro-file-map").default;
const { DiskCacheManager, HastePlugin } = require("metro-file-map");import FileMap from "metro-file-map";
const fileMap = new FileMap({
extensions: ['.js', '.json'],
platforms: ['ios', 'android', 'native'],
retainAllFiles: false,
rootDir: '/path/to/project',
roots: ['/path/to/project/src'],
maxWorkers: 4,
healthCheck: {
enabled: false,
interval: 30000,
timeout: 5000,
filePrefix: 'metro-file-map-health-check'
}
});
// Build the file map
const result = await fileMap.build();
const { fileSystem, hasteMap } = result;
// Query the file system
const allFiles = fileSystem.getAllFiles();
const moduleName = hasteMap.getModule('MyComponent');
// Clean up
await fileMap.end();Metro File Map is built around several key components:
Main FileMap class for orchestrating file system operations, watching, and caching.
class FileMap extends EventEmitter {
static create(options: InputOptions): FileMap;
constructor(options: InputOptions);
build(): Promise<BuildResult>;
read(): Promise<CacheData | null>;
end(): Promise<void>;
}
interface BuildResult {
fileSystem: FileSystem,
hasteMap: HasteMap,
mockMap: MockMap | null
}Virtual file system providing querying, lookup, and metadata operations.
interface FileSystem {
exists(file: string): boolean;
getAllFiles(): Array<string>;
getDependencies(file: string): Array<string> | null;
getModuleName(file: string): string | null;
getSha1(file: string): string | null;
matchFiles(opts: MatchFilesOptions): Iterable<string>;
lookup(mixedPath: string): LookupResult;
}Haste module resolution and conflict detection system.
interface HasteMap {
getModule(name: string, platform?: string, supportsNativePlatform?: boolean, type?: number): string | null;
getPackage(name: string, platform?: string, supportsNativePlatform?: boolean): string | null;
computeConflicts(): Array<HasteConflict>;
}Pluggable caching system with disk-based implementation for persistent storage.
interface CacheManager {
read(): Promise<CacheData | null>;
write(getSnapshot: () => CacheData, opts: CacheManagerWriteOptions): Promise<void>;
end(): Promise<void>;
}
class DiskCacheManager implements CacheManager {
constructor(options: CacheManagerFactoryOptions, config: DiskCacheConfig);
static getCacheFilePath(buildParameters: BuildParameters, cacheFilePrefix?: string, cacheDirectory?: string): string;
}Extensible plugin system for Haste modules, mocks, and custom file processing.
interface FileMapPlugin<SerializableState> {
+name: string;
initialize(initOptions: FileMapPluginInitOptions<SerializableState>): Promise<void>;
assertValid(): void;
bulkUpdate(delta: FileMapDelta): Promise<void>;
getSerializableSnapshot(): SerializableState;
onRemovedFile(relativeFilePath: string, fileMetadata: FileMetadata): void;
onNewOrModifiedFile(relativeFilePath: string, fileMetadata: FileMetadata): void;
getCacheKey(): string;
}Specialized error classes for Haste conflicts and duplicate candidates.
class HasteConflictsError extends Error {
constructor(conflicts: Array<HasteConflict>);
getDetailedMessage(pathsRelativeToRoot?: string): string;
}
class DuplicateHasteCandidatesError extends Error {
constructor(name: string, platform: string, supportsNativePlatform: boolean, duplicatesSet: DuplicatesSet);
}interface InputOptions {
// Required
extensions: ReadonlyArray<string>;
platforms: ReadonlyArray<string>;
retainAllFiles: boolean;
rootDir: string;
roots: ReadonlyArray<string>;
maxWorkers: number;
healthCheck: HealthCheckOptions;
// Optional
computeDependencies?: boolean;
computeSha1?: boolean;
enableSymlinks?: boolean;
forceNodeFilesystemAPI?: boolean;
ignorePattern?: RegExp;
mocksPattern?: string;
skipPackageJson?: boolean;
dependencyExtractor?: string;
hasteImplModulePath?: string;
perfLoggerFactory?: PerfLoggerFactory;
resetCache?: boolean;
throwOnModuleCollision?: boolean;
useWatchman?: boolean;
watch?: boolean;
watchmanDeferStates?: ReadonlyArray<string>;
console?: Console;
cacheManagerFactory?: CacheManagerFactory;
enableHastePackages?: boolean;
enableWorkerThreads?: boolean;
maxFilesPerWorker?: number;
}
interface HealthCheckOptions {
enabled: boolean;
interval: number;
timeout: number;
filePrefix: string;
}
interface ChangeEvent {
logger: RootPerfLogger | null;
eventsQueue: EventsQueue;
}
interface ChangeEventMetadata {
modifiedTime: number | null;
size: number | null;
type: 'f' | 'd' | 'l'; // File, Directory, Link
}
type FileMetadata = [
string, // id
number, // mtime
number, // size
0 | 1, // visited
string, // dependencies
string, // sha1
0 | 1 | string // symlink (0=no, 1=yes, string=target)
];
interface HasteConflict {
id: string;
platform: string | null;
absolutePaths: Array<string>;
type: 'duplicate' | 'shadowing';
}