metro 0.70.2 → 0.71.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/package.json +22 -21
  2. package/src/Assets.js.flow +4 -4
  3. package/src/Bundler/util.js +1 -1
  4. package/src/Bundler/util.js.flow +2 -2
  5. package/src/Bundler.js +17 -10
  6. package/src/Bundler.js.flow +19 -14
  7. package/src/DeltaBundler/DeltaCalculator.js +13 -17
  8. package/src/DeltaBundler/DeltaCalculator.js.flow +15 -20
  9. package/src/DeltaBundler/Serializers/getAllFiles.js.flow +2 -2
  10. package/src/DeltaBundler/Serializers/getAssets.js.flow +2 -2
  11. package/src/DeltaBundler/Serializers/getExplodedSourceMap.js.flow +4 -4
  12. package/src/DeltaBundler/Serializers/getRamBundleInfo.js.flow +6 -6
  13. package/src/DeltaBundler/Serializers/helpers/getSourceMapInfo.js.flow +4 -4
  14. package/src/DeltaBundler/Serializers/helpers/processBytecodeModules.js.flow +2 -2
  15. package/src/DeltaBundler/Serializers/helpers/processModules.js.flow +2 -2
  16. package/src/DeltaBundler/Serializers/hmrJSBundle.js.flow +2 -2
  17. package/src/DeltaBundler/Serializers/sourceMapGenerator.js.flow +6 -6
  18. package/src/DeltaBundler/Serializers/sourceMapObject.js.flow +4 -4
  19. package/src/DeltaBundler/Serializers/sourceMapString.js.flow +2 -2
  20. package/src/DeltaBundler/Worker.flow.js +78 -0
  21. package/src/DeltaBundler/Worker.flow.js.flow +121 -0
  22. package/src/DeltaBundler/Worker.js +8 -66
  23. package/src/DeltaBundler/Worker.js.flow +8 -107
  24. package/src/DeltaBundler/WorkerFarm.js.flow +4 -4
  25. package/src/DeltaBundler/__fixtures__/hasteImpl.js +4 -0
  26. package/src/DeltaBundler/getTransformCacheKey.js.flow +2 -2
  27. package/src/DeltaBundler/graphOperations.js +634 -0
  28. package/src/DeltaBundler/graphOperations.js.flow +749 -0
  29. package/src/DeltaBundler/types.flow.js.flow +36 -30
  30. package/src/DeltaBundler.js +14 -6
  31. package/src/DeltaBundler.js.flow +14 -10
  32. package/src/HmrServer.js.flow +6 -6
  33. package/src/IncrementalBundler.js +1 -1
  34. package/src/IncrementalBundler.js.flow +8 -8
  35. package/src/ModuleGraph/node-haste/ModuleCache.js +1 -1
  36. package/src/ModuleGraph/node-haste/ModuleCache.js.flow +1 -1
  37. package/src/ModuleGraph/node-haste/node-haste.flow.js.flow +2 -2
  38. package/src/ModuleGraph/node-haste/node-haste.js +4 -4
  39. package/src/ModuleGraph/node-haste/node-haste.js.flow +13 -7
  40. package/src/ModuleGraph/output/indexed-ram-bundle.js.flow +2 -2
  41. package/src/ModuleGraph/output/plain-bundle.js.flow +2 -2
  42. package/src/ModuleGraph/output/reverse-dependency-map-references.js.flow +8 -8
  43. package/src/ModuleGraph/output/util.js.flow +2 -2
  44. package/src/ModuleGraph/types.flow.js.flow +37 -37
  45. package/src/ModuleGraph/worker/collectDependencies.js.flow +2 -2
  46. package/src/Server/symbolicate.js.flow +1 -1
  47. package/src/Server.js.flow +18 -18
  48. package/src/cli.js +5 -0
  49. package/src/cli.js.flow +5 -0
  50. package/src/commands/build.js +4 -3
  51. package/src/commands/build.js.flow +5 -3
  52. package/src/commands/serve.js +3 -3
  53. package/src/commands/serve.js.flow +5 -3
  54. package/src/index.flow.js +392 -0
  55. package/src/index.flow.js.flow +480 -0
  56. package/src/index.js +8 -366
  57. package/src/index.js.flow +8 -456
  58. package/src/lib/bundleToBytecode.js.flow +2 -2
  59. package/src/lib/bundleToString.js.flow +2 -2
  60. package/src/lib/getPreludeCode.js.flow +2 -2
  61. package/src/lib/transformHelpers.js.flow +2 -2
  62. package/src/node-haste/DependencyGraph/ModuleResolution.js +17 -4
  63. package/src/node-haste/DependencyGraph/ModuleResolution.js.flow +20 -12
  64. package/src/node-haste/DependencyGraph/createHasteMap.js +79 -19
  65. package/src/node-haste/DependencyGraph/createHasteMap.js.flow +15 -14
  66. package/src/node-haste/DependencyGraph.js +31 -27
  67. package/src/node-haste/DependencyGraph.js.flow +43 -37
  68. package/src/node-haste/ModuleCache.js.flow +1 -1
  69. package/src/node-haste/lib/AssetPaths.js.flow +2 -2
  70. package/src/node-haste/lib/parsePlatformFilePath.js.flow +2 -2
  71. package/src/shared/output/RamBundle/as-indexed-file.js.flow +1 -1
  72. package/src/shared/output/RamBundle/buildSourcemapWithMetadata.js.flow +2 -2
  73. package/src/shared/types.flow.js.flow +14 -14
  74. package/src/DeltaBundler/computeDelta.js +0 -42
  75. package/src/DeltaBundler/computeDelta.js.flow +0 -47
  76. package/src/DeltaBundler/traverseDependencies.js +0 -470
  77. package/src/DeltaBundler/traverseDependencies.js.flow +0 -565
  78. package/src/node-haste/DependencyGraph/types.js +0 -10
  79. package/src/node-haste/DependencyGraph/types.js.flow +0 -88
package/src/index.js.flow CHANGED
@@ -10,461 +10,13 @@
10
10
 
11
11
  'use strict';
12
12
 
13
- import type {Graph} from './DeltaBundler';
14
- import type {ServerOptions} from './Server';
15
- import type {OutputOptions, RequestOptions} from './shared/types.flow.js';
16
- import type {Server as HttpServer} from 'http';
17
- import type {Server as HttpsServer} from 'https';
18
- import type {
19
- ConfigT,
20
- InputConfigT,
21
- Middleware,
22
- } from 'metro-config/src/configTypes.flow';
23
- import type {CustomTransformOptions} from 'metro-transform-worker';
24
- import typeof Yargs from 'yargs';
13
+ /*::
14
+ export type * from './index.flow';
15
+ */
25
16
 
26
- const makeBuildCommand = require('./commands/build');
27
- const makeDependenciesCommand = require('./commands/dependencies');
28
- const makeServeCommand = require('./commands/serve');
29
- const MetroHmrServer = require('./HmrServer');
30
- const IncrementalBundler = require('./IncrementalBundler');
31
- const createWebsocketServer = require('./lib/createWebsocketServer');
32
- const MetroServer = require('./Server');
33
- const outputBundle = require('./shared/output/bundle');
34
- const chalk = require('chalk');
35
- const fs = require('fs');
36
- const http = require('http');
37
- const https = require('https');
38
- const {getDefaultConfig, loadConfig, mergeConfig} = require('metro-config');
39
- const {InspectorProxy} = require('metro-inspector-proxy');
40
- const {parse} = require('url');
41
- const ws = require('ws');
17
+ try {
18
+ // $FlowFixMe[untyped-import]
19
+ require('metro-babel-register').unstable_registerForMetroMonorepo();
20
+ } catch {}
42
21
 
43
- type MetroMiddleWare = {|
44
- attachHmrServer: (httpServer: HttpServer | HttpsServer) => void,
45
- end: () => void,
46
- metroServer: MetroServer,
47
- middleware: Middleware,
48
- |};
49
-
50
- export type RunMetroOptions = {
51
- ...ServerOptions,
52
- waitForBundler?: boolean,
53
- };
54
-
55
- export type RunServerOptions = {|
56
- hasReducedPerformance?: boolean,
57
- host?: string,
58
- onError?: (Error & {|code?: string|}) => void,
59
- onReady?: (server: HttpServer | HttpsServer) => void,
60
- runInspectorProxy?: boolean,
61
- secureServerOptions?: Object,
62
- secure?: boolean, // deprecated
63
- secureCert?: string, // deprecated
64
- secureKey?: string, // deprecated
65
- waitForBundler?: boolean,
66
- websocketEndpoints?: {
67
- [path: string]: typeof ws.Server,
68
- },
69
- |};
70
-
71
- type BuildGraphOptions = {|
72
- entries: $ReadOnlyArray<string>,
73
- customTransformOptions?: CustomTransformOptions,
74
- dev?: boolean,
75
- minify?: boolean,
76
- onProgress?: (transformedFileCount: number, totalFileCount: number) => void,
77
- platform?: string,
78
- type?: 'module' | 'script',
79
- |};
80
-
81
- export type RunBuildOptions = {|
82
- entry: string,
83
- dev?: boolean,
84
- out?: string,
85
- onBegin?: () => void,
86
- onComplete?: () => void,
87
- onProgress?: (transformedFileCount: number, totalFileCount: number) => void,
88
- minify?: boolean,
89
- output?: {
90
- build: (
91
- MetroServer,
92
- RequestOptions,
93
- ) => Promise<{
94
- code: string,
95
- map: string,
96
- ...
97
- }>,
98
- save: (
99
- {
100
- code: string,
101
- map: string,
102
- ...
103
- },
104
- OutputOptions,
105
- (...args: Array<string>) => void,
106
- ) => Promise<mixed>,
107
- ...
108
- },
109
- platform?: string,
110
- sourceMap?: boolean,
111
- sourceMapUrl?: string,
112
- |};
113
-
114
- type BuildCommandOptions = {||} | null;
115
- type ServeCommandOptions = {||} | null;
116
-
117
- async function getConfig(config: InputConfigT): Promise<ConfigT> {
118
- const defaultConfig = await getDefaultConfig(config.projectRoot);
119
- return mergeConfig(defaultConfig, config);
120
- }
121
-
122
- async function runMetro(
123
- config: InputConfigT,
124
- options?: RunMetroOptions,
125
- ): Promise<MetroServer> {
126
- const mergedConfig = await getConfig(config);
127
- const {
128
- reporter,
129
- server: {port},
130
- } = mergedConfig;
131
-
132
- reporter.update({
133
- hasReducedPerformance: options
134
- ? Boolean(options.hasReducedPerformance)
135
- : false,
136
- port,
137
- type: 'initialize_started',
138
- });
139
-
140
- const {waitForBundler = false, ...serverOptions} = options ?? {};
141
- const server = new MetroServer(mergedConfig, serverOptions);
142
-
143
- const readyPromise = server
144
- .ready()
145
- .then(() => {
146
- reporter.update({
147
- type: 'initialize_done',
148
- port,
149
- });
150
- })
151
- .catch(error => {
152
- reporter.update({
153
- type: 'initialize_failed',
154
- port,
155
- error,
156
- });
157
- });
158
- if (waitForBundler) {
159
- await readyPromise;
160
- }
161
-
162
- return server;
163
- }
164
-
165
- exports.runMetro = runMetro;
166
- exports.loadConfig = loadConfig;
167
-
168
- const createConnectMiddleware = async function (
169
- config: ConfigT,
170
- options?: RunMetroOptions,
171
- ): Promise<MetroMiddleWare> {
172
- const metroServer = await runMetro(config, options);
173
-
174
- let enhancedMiddleware = metroServer.processRequest;
175
-
176
- // Enhance the resulting middleware using the config options
177
- if (config.server.enhanceMiddleware) {
178
- enhancedMiddleware = config.server.enhanceMiddleware(
179
- enhancedMiddleware,
180
- metroServer,
181
- );
182
- }
183
-
184
- return {
185
- attachHmrServer(httpServer: HttpServer | HttpsServer): void {
186
- const wss = createWebsocketServer({
187
- websocketServer: new MetroHmrServer(
188
- metroServer.getBundler(),
189
- metroServer.getCreateModuleId(),
190
- config,
191
- ),
192
- });
193
- httpServer.on('upgrade', (request, socket, head) => {
194
- const {pathname} = parse(request.url);
195
- if (pathname === '/hot') {
196
- wss.handleUpgrade(request, socket, head, ws => {
197
- wss.emit('connection', ws, request);
198
- });
199
- } else {
200
- socket.destroy();
201
- }
202
- });
203
- },
204
- metroServer,
205
- middleware: enhancedMiddleware,
206
- end(): void {
207
- metroServer.end();
208
- },
209
- };
210
- };
211
- exports.createConnectMiddleware = createConnectMiddleware;
212
-
213
- exports.runServer = async (
214
- config: ConfigT,
215
- {
216
- hasReducedPerformance = false,
217
- host,
218
- onError,
219
- onReady,
220
- secureServerOptions,
221
- secure, //deprecated
222
- secureCert, // deprecated
223
- secureKey, // deprecated
224
- waitForBundler = false,
225
- websocketEndpoints = {},
226
- }: RunServerOptions,
227
- ): Promise<HttpServer | HttpsServer> => {
228
- if (secure != null || secureCert != null || secureKey != null) {
229
- // eslint-disable-next-line no-console
230
- console.warn(
231
- chalk.inverse.yellow.bold(' DEPRECATED '),
232
- 'The `secure`, `secureCert`, and `secureKey` options are now deprecated. ' +
233
- 'Please use the `secureServerOptions` object instead to pass options to ' +
234
- "Metro's https development server.",
235
- );
236
- }
237
- // Lazy require
238
- const connect = require('connect');
239
-
240
- const serverApp = connect();
241
-
242
- const {middleware, end, metroServer} = await createConnectMiddleware(config, {
243
- hasReducedPerformance,
244
- waitForBundler,
245
- });
246
-
247
- serverApp.use(middleware);
248
-
249
- let inspectorProxy: ?InspectorProxy = null;
250
- if (config.server.runInspectorProxy) {
251
- inspectorProxy = new InspectorProxy(config.projectRoot);
252
- }
253
-
254
- let httpServer;
255
-
256
- if (secure || secureServerOptions != null) {
257
- let options = secureServerOptions;
258
- if (typeof secureKey === 'string' && typeof secureCert === 'string') {
259
- options = Object.assign(
260
- {
261
- key: fs.readFileSync(secureKey),
262
- cert: fs.readFileSync(secureCert),
263
- },
264
- secureServerOptions,
265
- );
266
- }
267
- httpServer = https.createServer(options, serverApp);
268
- } else {
269
- httpServer = http.createServer(serverApp);
270
- }
271
-
272
- httpServer.on('error', error => {
273
- if (onError) {
274
- onError(error);
275
- }
276
- end();
277
- });
278
-
279
- return new Promise(
280
- (
281
- resolve: (result: HttpServer | HttpsServer) => void,
282
- reject: mixed => mixed,
283
- ) => {
284
- httpServer.listen(config.server.port, host, () => {
285
- if (onReady) {
286
- onReady(httpServer);
287
- }
288
-
289
- Object.assign(websocketEndpoints, {
290
- ...(inspectorProxy
291
- ? {...inspectorProxy.createWebSocketListeners(httpServer)}
292
- : {}),
293
- '/hot': createWebsocketServer({
294
- websocketServer: new MetroHmrServer(
295
- metroServer.getBundler(),
296
- metroServer.getCreateModuleId(),
297
- config,
298
- ),
299
- }),
300
- });
301
-
302
- httpServer.on('upgrade', (request, socket, head) => {
303
- const {pathname} = parse(request.url);
304
- if (pathname != null && websocketEndpoints[pathname]) {
305
- websocketEndpoints[pathname].handleUpgrade(
306
- request,
307
- socket,
308
- head,
309
- ws => {
310
- websocketEndpoints[pathname].emit('connection', ws, request);
311
- },
312
- );
313
- } else {
314
- socket.destroy();
315
- }
316
- });
317
-
318
- if (inspectorProxy) {
319
- // TODO(hypuk): Refactor inspectorProxy.processRequest into separate request handlers
320
- // so that we could provide routes (/json/list and /json/version) here.
321
- // Currently this causes Metro to give warning about T31407894.
322
- // $FlowFixMe[method-unbinding] added when improving typing for this parameters
323
- serverApp.use(inspectorProxy.processRequest.bind(inspectorProxy));
324
- }
325
-
326
- resolve(httpServer);
327
- });
328
-
329
- // Disable any kind of automatic timeout behavior for incoming
330
- // requests in case it takes the packager more than the default
331
- // timeout of 120 seconds to respond to a request.
332
- httpServer.timeout = 0;
333
-
334
- httpServer.on('error', error => {
335
- end();
336
- reject(error);
337
- });
338
-
339
- httpServer.on('close', () => {
340
- end();
341
- });
342
- },
343
- );
344
- };
345
-
346
- exports.runBuild = async (
347
- config: ConfigT,
348
- {
349
- dev = false,
350
- entry,
351
- onBegin,
352
- onComplete,
353
- onProgress,
354
- minify = true,
355
- output = outputBundle,
356
- out,
357
- platform = 'web',
358
- sourceMap = false,
359
- sourceMapUrl,
360
- }: RunBuildOptions,
361
- ): Promise<{
362
- code: string,
363
- map: string,
364
- ...
365
- }> => {
366
- const metroServer = await runMetro(config, {
367
- watch: false,
368
- });
369
-
370
- try {
371
- const requestOptions: RequestOptions = {
372
- dev,
373
- entryFile: entry,
374
- inlineSourceMap: sourceMap && !sourceMapUrl,
375
- minify,
376
- platform,
377
- sourceMapUrl: sourceMap === false ? undefined : sourceMapUrl,
378
- createModuleIdFactory: config.serializer.createModuleIdFactory,
379
- onProgress,
380
- };
381
-
382
- if (onBegin) {
383
- onBegin();
384
- }
385
-
386
- const metroBundle = await output.build(metroServer, requestOptions);
387
-
388
- if (onComplete) {
389
- onComplete();
390
- }
391
-
392
- if (out) {
393
- const bundleOutput = out.replace(/(\.js)?$/, '.js');
394
- const sourcemapOutput =
395
- sourceMap === false ? undefined : out.replace(/(\.js)?$/, '.map');
396
-
397
- const outputOptions: OutputOptions = {
398
- bundleOutput,
399
- sourcemapOutput,
400
- dev,
401
- platform,
402
- };
403
-
404
- // eslint-disable-next-line no-console
405
- await output.save(metroBundle, outputOptions, console.log);
406
- }
407
-
408
- return metroBundle;
409
- } finally {
410
- await metroServer.end();
411
- }
412
- };
413
-
414
- exports.buildGraph = async function (
415
- config: InputConfigT,
416
- {
417
- customTransformOptions = Object.create(null),
418
- dev = false,
419
- entries,
420
- minify = false,
421
- onProgress,
422
- platform = 'web',
423
- type = 'module',
424
- }: BuildGraphOptions,
425
- ): Promise<Graph<>> {
426
- const mergedConfig = await getConfig(config);
427
-
428
- const bundler = new IncrementalBundler(mergedConfig);
429
-
430
- try {
431
- return await bundler.buildGraphForEntries(entries, {
432
- ...MetroServer.DEFAULT_GRAPH_OPTIONS,
433
- customTransformOptions,
434
- dev,
435
- minify,
436
- platform,
437
- type,
438
- });
439
- } finally {
440
- bundler.end();
441
- }
442
- };
443
-
444
- exports.attachMetroCli = function (
445
- yargs: Yargs,
446
- {
447
- build = {},
448
- serve = {},
449
- dependencies = {},
450
- }: {
451
- build: BuildCommandOptions,
452
- serve: ServeCommandOptions,
453
- dependencies: any,
454
- ...
455
- } = {},
456
- ): Yargs {
457
- if (build) {
458
- const {command, description, builder, handler} = makeBuildCommand();
459
- yargs.command(command, description, builder, handler);
460
- }
461
- if (serve) {
462
- const {command, description, builder, handler} = makeServeCommand();
463
- yargs.command(command, description, builder, handler);
464
- }
465
- if (dependencies) {
466
- const {command, description, builder, handler} = makeDependenciesCommand();
467
- yargs.command(command, description, builder, handler);
468
- }
469
- return yargs;
470
- };
22
+ module.exports = require('./index.flow');
@@ -49,10 +49,10 @@ function addModuleHeader(buffer: Buffer): [Buffer, Buffer] {
49
49
  * ...
50
50
  *
51
51
  */
52
- function bundleToBytecode(bundle: BytecodeBundle): {|
52
+ function bundleToBytecode(bundle: BytecodeBundle): {
53
53
  +bytecode: Buffer,
54
54
  +metadata: BundleMetadata,
55
- |} {
55
+ } {
56
56
  const buffers = [];
57
57
 
58
58
  if (bundle.pre.length) {
@@ -18,10 +18,10 @@ import type {
18
18
  /**
19
19
  * Serializes a bundle into a plain JS bundle.
20
20
  */
21
- function bundleToString(bundle: Bundle): {|
21
+ function bundleToString(bundle: Bundle): {
22
22
  +code: string,
23
23
  +metadata: BundleMetadata,
24
- |} {
24
+ } {
25
25
  let code = bundle.pre.length > 0 ? bundle.pre + '\n' : '';
26
26
  const modules = [];
27
27
 
@@ -14,11 +14,11 @@ function getPreludeCode({
14
14
  extraVars,
15
15
  isDev,
16
16
  globalPrefix,
17
- }: {|
17
+ }: {
18
18
  +extraVars?: {[string]: mixed, ...},
19
19
  +isDev: boolean,
20
20
  +globalPrefix: string,
21
- |}): string {
21
+ }): string {
22
22
  const vars = [
23
23
  '__BUNDLE_START_TIME__=this.nativePerformanceNow?nativePerformanceNow():Date.now()',
24
24
  `__DEV__=${String(isDev)}`,
@@ -21,10 +21,10 @@ const path = require('path');
21
21
 
22
22
  type InlineRequiresRaw = {+blockList: {[string]: true, ...}, ...} | boolean;
23
23
 
24
- type TransformOptionsWithRawInlines = {|
24
+ type TransformOptionsWithRawInlines = {
25
25
  ...TransformOptions,
26
26
  +inlineRequires: InlineRequiresRaw,
27
- |};
27
+ };
28
28
 
29
29
  const baseIgnoredInlineRequires = ['React', 'react', 'react-native'];
30
30
 
@@ -144,12 +144,16 @@ class ModuleResolver {
144
144
  ` * ${Resolver.formatFileCandidates(
145
145
  this._removeRoot(candidates.dir)
146
146
  )}`,
147
- ].join("\n")
147
+ ].join("\n"),
148
+ {
149
+ cause: error,
150
+ }
148
151
  );
149
152
  }
150
153
 
151
154
  if (error instanceof Resolver.FailedToResolveNameError) {
152
- const { dirPaths, extraPaths } = error;
155
+ const dirPaths = error.dirPaths;
156
+ const extraPaths = error.extraPaths;
153
157
  const displayDirPaths = dirPaths
154
158
  .filter((dirPath) => this._options.dirExists(dirPath))
155
159
  .map((dirPath) => path.relative(this._options.projectRoot, dirPath))
@@ -161,7 +165,10 @@ class ModuleResolver {
161
165
  [
162
166
  `${moduleName} could not be found within the project${hint || "."}`,
163
167
  ...displayDirPaths.map((dirPath) => ` ${dirPath}`),
164
- ].join("\n")
168
+ ].join("\n"),
169
+ {
170
+ cause: error,
171
+ }
165
172
  );
166
173
  }
167
174
 
@@ -237,7 +244,11 @@ class UnableToResolveError extends Error {
237
244
  * The name of the module that was required, no necessarily a path,
238
245
  * ex. `./bar`, or `invariant`.
239
246
  */
240
- constructor(originModulePath, targetModuleName, message) {
247
+
248
+ /**
249
+ * Original error that causes this error
250
+ */
251
+ constructor(originModulePath, targetModuleName, message, options) {
241
252
  super();
242
253
  this.originModulePath = originModulePath;
243
254
  this.targetModuleName = targetModuleName;
@@ -249,6 +260,8 @@ class UnableToResolveError extends Error {
249
260
  originModulePath,
250
261
  message
251
262
  ) + (codeFrameMessage ? "\n" + codeFrameMessage : "");
263
+ this.cause =
264
+ options === null || options === void 0 ? void 0 : options.cause;
252
265
  }
253
266
 
254
267
  buildCodeFrameMessage() {
@@ -10,7 +10,7 @@
10
10
 
11
11
  'use strict';
12
12
 
13
- import type {ModuleMap} from './types';
13
+ import type {ModuleMap} from 'metro-file-map';
14
14
  import type {
15
15
  CustomResolver,
16
16
  DoesFileExist,
@@ -53,7 +53,7 @@ export type ModuleishCache<TModule, TPackage> = interface {
53
53
  getPackageOf(modulePath: string): ?TPackage,
54
54
  };
55
55
 
56
- type Options<TModule, TPackage> = {|
56
+ type Options<TModule, TPackage> = {
57
57
  +dirExists: DirExistsFn,
58
58
  +disableHierarchicalLookup: boolean,
59
59
  +doesFileExist: DoesFileExist,
@@ -69,7 +69,7 @@ type Options<TModule, TPackage> = {|
69
69
  +resolveAsset: ResolveAsset,
70
70
  +resolveRequest: ?CustomResolver,
71
71
  +sourceExts: $ReadOnlyArray<string>,
72
- |};
72
+ };
73
73
 
74
74
  class ModuleResolver<TModule: Moduleish, TPackage: Packageish> {
75
75
  _options: Options<TModule, TPackage>;
@@ -201,18 +201,14 @@ class ModuleResolver<TModule: Moduleish, TPackage: Packageish> {
201
201
  this._removeRoot(candidates.dir),
202
202
  )}`,
203
203
  ].join('\n'),
204
+ {
205
+ cause: error,
206
+ },
204
207
  );
205
208
  }
206
209
  if (error instanceof Resolver.FailedToResolveNameError) {
207
- const {
208
- dirPaths,
209
- extraPaths,
210
- }: {
211
- // $flowfixme these types are defined explicitly in FailedToResolveNameError but Flow refuses to recognize them here
212
- dirPaths: $ReadOnlyArray<string>,
213
- extraPaths: $ReadOnlyArray<string>,
214
- ...
215
- } = error;
210
+ const dirPaths = error.dirPaths;
211
+ const extraPaths = error.extraPaths;
216
212
  const displayDirPaths = dirPaths
217
213
  .filter((dirPath: string) => this._options.dirExists(dirPath))
218
214
  .map(dirPath => path.relative(this._options.projectRoot, dirPath))
@@ -227,6 +223,9 @@ class ModuleResolver<TModule: Moduleish, TPackage: Packageish> {
227
223
  `${moduleName} could not be found within the project${hint || '.'}`,
228
224
  ...displayDirPaths.map((dirPath: string) => ` ${dirPath}`),
229
225
  ].join('\n'),
226
+ {
227
+ cause: error,
228
+ },
230
229
  );
231
230
  }
232
231
  throw error;
@@ -294,11 +293,18 @@ class UnableToResolveError extends Error {
294
293
  * ex. `./bar`, or `invariant`.
295
294
  */
296
295
  targetModuleName: string;
296
+ /**
297
+ * Original error that causes this error
298
+ */
299
+ cause: ?Error;
297
300
 
298
301
  constructor(
299
302
  originModulePath: string,
300
303
  targetModuleName: string,
301
304
  message: string,
305
+ options?: $ReadOnly<{
306
+ cause?: Error,
307
+ }>,
302
308
  ) {
303
309
  super();
304
310
  this.originModulePath = originModulePath;
@@ -311,6 +317,8 @@ class UnableToResolveError extends Error {
311
317
  originModulePath,
312
318
  message,
313
319
  ) + (codeFrameMessage ? '\n' + codeFrameMessage : '');
320
+
321
+ this.cause = options?.cause;
314
322
  }
315
323
 
316
324
  buildCodeFrameMessage(): ?string {