0
# Module Resolution
1
2
Module resolution system that maps module names to file paths with support for platform-specific extensions, package.json resolution, and mock files. The ModuleMap provides efficient lookups for module names, packages, and mocks with full platform support.
3
4
## Capabilities
5
6
### Module Resolution
7
8
Core module resolution functionality for finding files by module name with platform support.
9
10
```typescript { .api }
11
/**
12
* Resolve a module name to its file path
13
* @param name - Module name to resolve
14
* @param platform - Target platform (e.g., 'ios', 'android', 'web')
15
* @param supportsNativePlatform - Whether to support React Native platform resolution
16
* @param type - Module type filter (MODULE or PACKAGE)
17
* @returns Absolute path to module file, or null if not found
18
*/
19
getModule(
20
name: string,
21
platform?: string | null,
22
supportsNativePlatform?: boolean | null,
23
type?: HTypeValue | null
24
): string | null;
25
26
/**
27
* Resolve a package name to its package.json file path
28
* @param name - Package name to resolve
29
* @param platform - Target platform for platform-specific packages
30
* @param _supportsNativePlatform - Platform support flag (unused in current implementation)
31
* @returns Absolute path to package.json, or null if not found
32
*/
33
getPackage(
34
name: string,
35
platform: string | null | undefined,
36
_supportsNativePlatform: boolean | null
37
): string | null;
38
39
/**
40
* Get the file path for a mock module
41
* @param name - Module name to find mock for
42
* @returns Absolute path to mock file, or undefined if no mock exists
43
*/
44
getMockModule(name: string): string | undefined;
45
```
46
47
### Data Access and Serialization
48
49
Methods for accessing raw module map data and serializing for caching.
50
51
```typescript { .api }
52
/**
53
* Get the raw internal module map data structure
54
* @returns Raw module map with all internal data
55
*/
56
getRawModuleMap(): RawModuleMap;
57
58
/**
59
* Serialize the module map to JSON for caching or transmission
60
* @returns Serializable representation of the module map
61
*/
62
toJSON(): SerializableModuleMap;
63
```
64
65
### Static Factory Methods
66
67
Factory methods for creating ModuleMap instances.
68
69
```typescript { .api }
70
/**
71
* Create a new empty ModuleMap
72
* @param rootDir - Root directory for the module map
73
* @returns New ModuleMap instance
74
*/
75
static create(rootDir: string): ModuleMap;
76
77
/**
78
* Create ModuleMap from serialized JSON data
79
* @param serializableModuleMap - Previously serialized module map data
80
* @returns ModuleMap instance restored from JSON
81
*/
82
static fromJSON(serializableModuleMap: SerializableModuleMap): ModuleMap;
83
```
84
85
### Exported ModuleMap Utility
86
87
Convenient export for creating ModuleMap instances.
88
89
```typescript { .api }
90
/**
91
* Exported ModuleMap utility object with create method
92
*/
93
const ModuleMap = {
94
/**
95
* Create new ModuleMap instance
96
* @param rootPath - Root directory path
97
* @returns IModuleMap interface implementation
98
*/
99
create: (rootPath: string) => IModuleMap;
100
};
101
```
102
103
**Usage Examples:**
104
105
```typescript
106
import HasteMap, { ModuleMap } from "jest-haste-map";
107
108
// Build haste map and get module map
109
const hasteMap = await HasteMap.create({
110
id: "my-app",
111
extensions: ["js", "ts", "jsx", "tsx"],
112
maxWorkers: 4,
113
platforms: ["ios", "android", "web"],
114
roots: ["/src"],
115
retainAllFiles: true,
116
rootDir: "/project/root",
117
});
118
119
const {moduleMap} = await hasteMap.build();
120
121
// Resolve module by name
122
const buttonPath = moduleMap.getModule("Button");
123
if (buttonPath) {
124
console.log("Button component found at:", buttonPath);
125
}
126
127
// Platform-specific resolution
128
const iosButtonPath = moduleMap.getModule("Button", "ios", true);
129
const androidButtonPath = moduleMap.getModule("Button", "android", true);
130
const webButtonPath = moduleMap.getModule("Button", "web", true);
131
132
console.log("Platform-specific Button components:");
133
console.log("iOS:", iosButtonPath);
134
console.log("Android:", androidButtonPath);
135
console.log("Web:", webButtonPath);
136
137
// Package resolution
138
const reactPackage = moduleMap.getPackage("react", null, false);
139
if (reactPackage) {
140
console.log("React package.json found at:", reactPackage);
141
}
142
143
// Mock resolution
144
const buttonMock = moduleMap.getMockModule("Button");
145
if (buttonMock) {
146
console.log("Button mock found at:", buttonMock);
147
}
148
149
// Create standalone module map
150
const standaloneMap = ModuleMap.create("/different/project");
151
152
// Serialize for caching
153
const serialized = moduleMap.toJSON();
154
console.log("Serialized module map:", serialized);
155
156
// Restore from serialized data
157
const restoredMap = ModuleMap.fromJSON(serialized);
158
159
// Access raw data for advanced use cases
160
const rawData = moduleMap.getRawModuleMap();
161
console.log("Module count:", rawData.map.size);
162
console.log("Mock count:", rawData.mocks.size);
163
console.log("Duplicates:", rawData.duplicates.size);
164
```
165
166
### Data Types and Structures
167
168
Core data structures used by the module resolution system.
169
170
```typescript { .api }
171
/**
172
* Raw internal module map data structure
173
*/
174
interface RawModuleMap {
175
/** Root directory for resolving relative paths */
176
rootDir: string;
177
/** Map of duplicate module names to their conflict information */
178
duplicates: DuplicatesIndex;
179
/** Map of module names to platform-specific file metadata */
180
map: ModuleMapData;
181
/** Map of mock names to file paths */
182
mocks: MockData;
183
}
184
185
/**
186
* Platform-specific module metadata mapping
187
*/
188
type ModuleMapItem = {[platform: string]: ModuleMetaData};
189
190
/**
191
* Module metadata stored as array for efficiency
192
* [path, type]
193
*/
194
type ModuleMetaData = [path: string, type: number];
195
196
/**
197
* Serializable representation for caching and transmission
198
*/
199
interface SerializableModuleMap {
200
/** Serialized duplicates data */
201
duplicates: ReadonlyArray<[string, [string, [string, [string, number]]]]>;
202
/** Serialized module map data */
203
map: ReadonlyArray<[string, ModuleMapItem]>;
204
/** Serialized mocks data */
205
mocks: ReadonlyArray<[string, string]>;
206
/** Root directory path */
207
rootDir: string;
208
}
209
210
/**
211
* Module type constants
212
*/
213
interface HType {
214
MODULE: 0; // Regular module file
215
PACKAGE: 1; // package.json file
216
GENERIC_PLATFORM: 'g'; // Generic platform identifier
217
NATIVE_PLATFORM: 'native'; // React Native platform identifier
218
}
219
220
type HTypeValue = HType[keyof HType];
221
222
/**
223
* Type definitions for internal data structures
224
*/
225
type ModuleMapData = Map<string, ModuleMapItem>;
226
type MockData = Map<string, string>;
227
type DuplicatesIndex = Map<string, Map<string, DuplicatesSet>>;
228
type DuplicatesSet = Map<string, number>;
229
```
230
231
### Error Handling
232
233
Error classes for handling module resolution conflicts.
234
235
```typescript { .api }
236
/**
237
* Error thrown when multiple files claim the same module name
238
*/
239
class DuplicateHasteCandidatesError extends Error {
240
/** The conflicting module name */
241
hasteName: string;
242
/** The platform where the conflict occurred */
243
platform: string | null;
244
/** Whether native platform support was enabled */
245
supportsNativePlatform: boolean;
246
/** Set of conflicting file paths and their types */
247
duplicatesSet: DuplicatesSet;
248
249
constructor(
250
name: string,
251
platform: string,
252
supportsNativePlatform: boolean,
253
duplicatesSet: DuplicatesSet
254
);
255
}
256
```
257
258
### Platform-Specific Resolution
259
260
Platform-specific module resolution follows a priority order:
261
262
1. **Specific Platform**: `Button.ios.js` for platform "ios"
263
2. **Native Platform**: `Button.native.js` if `supportsNativePlatform` is true
264
3. **Generic Platform**: `Button.js` as fallback
265
266
```typescript
267
// Example of platform resolution priority
268
const moduleMap = await hasteMap.build().then(result => result.moduleMap);
269
270
// This will look for files in order:
271
// 1. Button.ios.js (or Button.ios.ts, etc.)
272
// 2. Button.native.js (if supportsNativePlatform is true)
273
// 3. Button.js (generic fallback)
274
const iosButton = moduleMap.getModule("Button", "ios", true);
275
276
// Force specific type resolution
277
const packageOnly = moduleMap.getModule("some-package", null, false, 1); // PACKAGE type only
278
const moduleOnly = moduleMap.getModule("SomeModule", null, false, 0); // MODULE type only
279
```
280
281
### Integration with HasteFS
282
283
ModuleMap works seamlessly with HasteFS for complete project introspection:
284
285
```typescript
286
const {hasteFS, moduleMap} = await hasteMap.build();
287
288
// Find module and check if it exists
289
const utilsPath = moduleMap.getModule("utils");
290
if (utilsPath && hasteFS.exists(utilsPath)) {
291
const dependencies = hasteFS.getDependencies(utilsPath);
292
const size = hasteFS.getSize(utilsPath);
293
console.log(`Utils module: ${utilsPath} (${size} bytes, ${dependencies?.length || 0} deps)`);
294
}
295
296
// Find all modules of a certain type
297
const rawMap = moduleMap.getRawModuleMap();
298
for (const [moduleName, platformMap] of rawMap.map) {
299
for (const [platform, [path, type]] of Object.entries(platformMap)) {
300
if (type === 0) { // MODULE type
301
console.log(`Module ${moduleName} (${platform}): ${path}`);
302
}
303
}
304
}
305
```