0
# Utilities
1
2
Additional utility functions for source map manipulation, conversion, and path normalization used throughout the Metro source map ecosystem.
3
4
## Capabilities
5
6
### Source Map Conversion
7
8
Convert between different source map formats and segment representations.
9
10
```javascript { .api }
11
/**
12
* Converts a standard source map object into Babel-compatible segments
13
* @param sourceMap - Basic source map object with mappings
14
* @returns Array of Babel source map segments for further processing
15
*/
16
function toBabelSegments(sourceMap: BasicSourceMap): Array<BabelSourceMapSegment>;
17
18
/**
19
* Converts a Babel source map segment into Metro's tuple format
20
* @param mapping - Babel source map segment object
21
* @returns Metro source map segment tuple (2, 4, or 5 elements)
22
*/
23
function toSegmentTuple(mapping: BabelSourceMapSegment): MetroSourceMapSegmentTuple;
24
```
25
26
**Usage Examples:**
27
28
```javascript
29
const { toBabelSegments, toSegmentTuple } = require("metro-source-map");
30
31
// Convert source map to Babel segments
32
const sourceMap = {
33
version: 3,
34
sources: ["app.js"],
35
names: ["console", "log"],
36
mappings: "AAAA,QAAQ,CAAC,GAAG",
37
sourcesContent: ["console.log('hello');"]
38
};
39
40
const babelSegments = toBabelSegments(sourceMap);
41
console.log(babelSegments);
42
// [
43
// {
44
// generated: { line: 1, column: 0 },
45
// original: { line: 1, column: 0 },
46
// source: "app.js",
47
// name: null
48
// },
49
// {
50
// generated: { line: 1, column: 8 },
51
// original: { line: 1, column: 8 },
52
// source: "app.js",
53
// name: "console"
54
// }
55
// ]
56
57
// Convert Babel segment back to Metro tuple
58
const segment = {
59
generated: { line: 1, column: 8 },
60
original: { line: 1, column: 8 },
61
source: "app.js",
62
name: "console"
63
};
64
65
const tuple = toSegmentTuple(segment);
66
console.log(tuple); // [1, 8, 1, 8, "console"]
67
```
68
69
### Path Normalization
70
71
Normalize source paths for consistent source map references across different platforms and environments.
72
73
```javascript { .api }
74
/**
75
* Normalizes source file paths for consistent source map references
76
* @param source - Source file path to normalize
77
* @param sourceRoot - Optional source root directory
78
* @returns Normalized source path
79
*/
80
function normalizeSourcePath(source: string, sourceRoot?: ?string): string;
81
```
82
83
**Usage Examples:**
84
85
```javascript
86
const { normalizeSourcePath } = require("metro-source-map");
87
88
// Basic path normalization
89
const normalized1 = normalizeSourcePath("./src/app.js");
90
console.log(normalized1); // "src/app.js"
91
92
// With source root
93
const normalized2 = normalizeSourcePath("../components/Button.js", "/project/src/");
94
console.log(normalized2); // "components/Button.js"
95
96
// Absolute path normalization
97
const normalized3 = normalizeSourcePath("/home/user/project/src/utils.js", "/home/user/project/");
98
console.log(normalized3); // "src/utils.js"
99
100
// Windows path normalization (when running on Windows)
101
const normalized4 = normalizeSourcePath("src\\components\\App.js");
102
console.log(normalized4); // "src/components/App.js"
103
```
104
105
### Segment Type Definitions
106
107
Types for working with different source map segment formats.
108
109
```javascript { .api }
110
/**
111
* Babel source map segment format
112
*/
113
interface BabelSourceMapSegment {
114
/** Generated code position */
115
generated: {
116
line: number;
117
column: number;
118
};
119
/** Original source position (optional) */
120
original?: {
121
line: number;
122
column: number;
123
};
124
/** Source file path (optional) */
125
source?: ?string;
126
/** Symbol name (optional) */
127
name?: ?string;
128
}
129
130
/**
131
* Metro source map segment tuple formats
132
*/
133
type MetroSourceMapSegmentTuple =
134
| [number, number] // Generated position only
135
| [number, number, number, number] // Generated -> Original position
136
| [number, number, number, number, string]; // Generated -> Original position + name
137
```
138
139
### Advanced Conversion Usage
140
141
```javascript
142
const { toBabelSegments, toSegmentTuple, normalizeSourcePath } = require("metro-source-map");
143
144
// Process source map with path normalization
145
function processSourceMapWithNormalizedPaths(sourceMap, sourceRoot) {
146
// Convert to Babel segments for processing
147
const segments = toBabelSegments(sourceMap);
148
149
// Normalize all source paths
150
const normalizedSegments = segments.map(segment => ({
151
...segment,
152
source: segment.source ? normalizeSourcePath(segment.source, sourceRoot) : segment.source
153
}));
154
155
// Convert back to Metro tuples
156
const tuples = normalizedSegments.map(toSegmentTuple);
157
158
return tuples;
159
}
160
161
// Usage
162
const sourceMap = {
163
version: 3,
164
sources: ["./src/app.js", "../utils/helper.js"],
165
names: ["main", "helper"],
166
mappings: "AAAA,SAAS,MAAM,CAAC,CAAC,CAAC"
167
};
168
169
const processedTuples = processSourceMapWithNormalizedPaths(sourceMap, "/project/");
170
console.log(processedTuples);
171
```
172
173
### Integration with Source Map Generation
174
175
```javascript
176
const { toSegmentTuple, fromRawMappings, normalizeSourcePath } = require("metro-source-map");
177
178
// Convert external source map data to Metro format
179
function convertExternalSourceMap(externalMap) {
180
// External source map might use different segment format
181
const externalSegments = externalMap.segments; // Assume some external format
182
183
// Convert to Metro tuples
184
const metroTuples = externalSegments.map(segment => {
185
// Convert external format to Babel format first
186
const babelSegment = {
187
generated: { line: segment.genLine, column: segment.genCol },
188
original: segment.srcLine ? { line: segment.srcLine, column: segment.srcCol } : undefined,
189
source: segment.source ? normalizeSourcePath(segment.source) : undefined,
190
name: segment.name
191
};
192
193
// Convert to Metro tuple
194
return toSegmentTuple(babelSegment);
195
});
196
197
return metroTuples;
198
}
199
200
// Use converted tuples in Metro source map generation
201
function generateFromExternalMap(externalMap, moduleInfo) {
202
const metroTuples = convertExternalSourceMap(externalMap);
203
204
const modules = [{
205
map: metroTuples,
206
path: normalizeSourcePath(moduleInfo.path),
207
source: moduleInfo.source,
208
code: moduleInfo.code,
209
isIgnored: false
210
}];
211
212
return fromRawMappings(modules);
213
}
214
```
215
216
### Path Normalization Edge Cases
217
218
```javascript
219
const { normalizeSourcePath } = require("metro-source-map");
220
221
// Handle various path formats
222
const testPaths = [
223
"./src/app.js", // Relative path
224
"../components/Button.js", // Parent directory
225
"/absolute/path/file.js", // Absolute path
226
"simple.js", // Simple filename
227
"src\\windows\\path.js", // Windows path separators
228
"//network/share/file.js", // Network path
229
"C:\\Windows\\file.js", // Windows absolute
230
"" // Empty string
231
];
232
233
testPaths.forEach(path => {
234
const normalized = normalizeSourcePath(path, "/project/src/");
235
console.log(`${path} -> ${normalized}`);
236
});
237
238
// Custom normalization with validation
239
function safeNormalizeSourcePath(source, sourceRoot) {
240
try {
241
if (!source || typeof source !== 'string') {
242
return source;
243
}
244
return normalizeSourcePath(source, sourceRoot);
245
} catch (error) {
246
console.warn(`Path normalization failed for "${source}":`, error);
247
return source; // Return original path if normalization fails
248
}
249
}
250
```
251
252
## Error Handling
253
254
Utility functions may encounter errors in the following cases:
255
256
- **Invalid source maps**: When `toBabelSegments` receives malformed source map data
257
- **Invalid segments**: When `toSegmentTuple` receives segments with missing required properties
258
- **Path resolution errors**: When `normalizeSourcePath` cannot resolve complex path structures
259
260
```javascript
261
const { toBabelSegments, toSegmentTuple, normalizeSourcePath } = require("metro-source-map");
262
263
// Safe conversion with error handling
264
function safeToBabelSegments(sourceMap) {
265
try {
266
return toBabelSegments(sourceMap);
267
} catch (error) {
268
console.error('Failed to convert source map to Babel segments:', error);
269
return [];
270
}
271
}
272
273
function safeToSegmentTuple(segment) {
274
try {
275
return toSegmentTuple(segment);
276
} catch (error) {
277
console.warn('Failed to convert segment to tuple:', error);
278
// Return a simple generated-only mapping as fallback
279
return [segment.generated.line, segment.generated.column];
280
}
281
}
282
283
// Robust path normalization
284
function robustNormalizeSourcePath(source, sourceRoot) {
285
if (!source || typeof source !== 'string') {
286
return source;
287
}
288
289
try {
290
return normalizeSourcePath(source, sourceRoot);
291
} catch (error) {
292
// Log the error but don't fail the entire process
293
console.debug(`Path normalization warning for "${source}":`, error.message);
294
return source;
295
}
296
}
297
```