metro 0.70.3 → 0.71.2

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 (94) hide show
  1. package/package.json +23 -22
  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 +15 -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 +641 -0
  28. package/src/DeltaBundler/graphOperations.js.flow +752 -0
  29. package/src/DeltaBundler/types.flow.js +6 -0
  30. package/src/DeltaBundler/types.flow.js.flow +43 -31
  31. package/src/DeltaBundler.js +12 -6
  32. package/src/DeltaBundler.js.flow +14 -10
  33. package/src/HmrServer.js +0 -2
  34. package/src/HmrServer.js.flow +7 -8
  35. package/src/IncrementalBundler.js +1 -1
  36. package/src/IncrementalBundler.js.flow +8 -8
  37. package/src/ModuleGraph/node-haste/ModuleCache.js +1 -1
  38. package/src/ModuleGraph/node-haste/ModuleCache.js.flow +1 -1
  39. package/src/ModuleGraph/node-haste/node-haste.flow.js +0 -1
  40. package/src/ModuleGraph/node-haste/node-haste.flow.js.flow +3 -4
  41. package/src/ModuleGraph/node-haste/node-haste.js +4 -4
  42. package/src/ModuleGraph/node-haste/node-haste.js.flow +13 -7
  43. package/src/ModuleGraph/output/indexed-ram-bundle.js.flow +2 -2
  44. package/src/ModuleGraph/output/plain-bundle.js.flow +2 -2
  45. package/src/ModuleGraph/output/reverse-dependency-map-references.js.flow +8 -8
  46. package/src/ModuleGraph/output/util.js.flow +2 -2
  47. package/src/ModuleGraph/types.flow.js.flow +37 -37
  48. package/src/ModuleGraph/worker/collectDependencies.js +215 -8
  49. package/src/ModuleGraph/worker/collectDependencies.js.flow +230 -13
  50. package/src/Server/symbolicate.js.flow +1 -1
  51. package/src/Server.js.flow +18 -18
  52. package/src/cli.js +5 -0
  53. package/src/cli.js.flow +5 -0
  54. package/src/commands/build.js +4 -3
  55. package/src/commands/build.js.flow +5 -3
  56. package/src/commands/serve.js +3 -3
  57. package/src/commands/serve.js.flow +5 -3
  58. package/src/index.flow.js +392 -0
  59. package/src/index.flow.js.flow +480 -0
  60. package/src/index.js +8 -366
  61. package/src/index.js.flow +8 -456
  62. package/src/lib/CountingSet.js +116 -0
  63. package/src/lib/CountingSet.js.flow +126 -0
  64. package/src/lib/JsonReporter.js +0 -2
  65. package/src/lib/JsonReporter.js.flow +1 -1
  66. package/src/lib/bundleToBytecode.js.flow +2 -2
  67. package/src/lib/bundleToString.js.flow +2 -2
  68. package/src/lib/getAppendScripts.js +10 -4
  69. package/src/lib/getAppendScripts.js.flow +6 -4
  70. package/src/lib/getPreludeCode.js +19 -1
  71. package/src/lib/getPreludeCode.js.flow +17 -2
  72. package/src/lib/getPrependedScripts.js +10 -2
  73. package/src/lib/getPrependedScripts.js.flow +11 -2
  74. package/src/lib/reporting.js +0 -2
  75. package/src/lib/reporting.js.flow +2 -1
  76. package/src/lib/transformHelpers.js.flow +2 -2
  77. package/src/node-haste/DependencyGraph/ModuleResolution.js +17 -4
  78. package/src/node-haste/DependencyGraph/ModuleResolution.js.flow +20 -12
  79. package/src/node-haste/DependencyGraph/createHasteMap.js +80 -19
  80. package/src/node-haste/DependencyGraph/createHasteMap.js.flow +16 -14
  81. package/src/node-haste/DependencyGraph.js +31 -29
  82. package/src/node-haste/DependencyGraph.js.flow +44 -38
  83. package/src/node-haste/ModuleCache.js.flow +1 -1
  84. package/src/node-haste/lib/AssetPaths.js.flow +2 -2
  85. package/src/node-haste/lib/parsePlatformFilePath.js.flow +2 -2
  86. package/src/shared/output/RamBundle/as-indexed-file.js.flow +1 -1
  87. package/src/shared/output/RamBundle/buildSourcemapWithMetadata.js.flow +2 -2
  88. package/src/shared/types.flow.js.flow +14 -14
  89. package/src/DeltaBundler/computeDelta.js +0 -42
  90. package/src/DeltaBundler/computeDelta.js.flow +0 -47
  91. package/src/DeltaBundler/traverseDependencies.js +0 -470
  92. package/src/DeltaBundler/traverseDependencies.js.flow +0 -565
  93. package/src/node-haste/DependencyGraph/types.js +0 -10
  94. package/src/node-haste/DependencyGraph/types.js.flow +0 -88
@@ -37,6 +37,20 @@ export type Dependency<TSplitCondition> = $ReadOnly<{
37
37
  name: string,
38
38
  }>;
39
39
 
40
+ // TODO: Convert to a Flow enum
41
+ type ContextMode = 'sync' | 'eager' | 'lazy' | 'lazy-once';
42
+
43
+ type ContextFilter = {pattern: string, flags: string};
44
+
45
+ export type RequireContextParams = $ReadOnly<{
46
+ /* Should search for files recursively. Optional, default `true` when `require.context` is used */
47
+ recursive: boolean,
48
+ /* Filename filter pattern for use in `require.context`. Optional, default `.*` (any file) when `require.context` is used */
49
+ filter: $ReadOnly<ContextFilter>,
50
+ /** Mode for resolving dynamic dependencies. Defaults to `sync` */
51
+ mode: ContextMode,
52
+ }>;
53
+
40
54
  type DependencyData<TSplitCondition> = $ReadOnly<{
41
55
  // If null, then the dependency is synchronous.
42
56
  // (ex. `require('foo')`)
@@ -45,6 +59,8 @@ type DependencyData<TSplitCondition> = $ReadOnly<{
45
59
  // If left unspecified, then the dependency is unconditionally split.
46
60
  splitCondition?: TSplitCondition,
47
61
  locs: Array<BabelSourceLocation>,
62
+ /** Context for requiring a collection of modules. */
63
+ contextParams?: RequireContextParams,
48
64
  }>;
49
65
 
50
66
  export type MutableInternalDependency<TSplitCondition> = {
@@ -66,6 +82,8 @@ export type State<TSplitCondition> = {
66
82
  dependencyMapIdentifier: ?Identifier,
67
83
  keepRequireNames: boolean,
68
84
  allowOptionalDependencies: AllowOptionalDependencies,
85
+ /** Enable `require.context` statements which can be used to import multiple files in a directory. */
86
+ unstable_allowRequireContext: boolean,
69
87
  };
70
88
 
71
89
  export type Options<TSplitCondition = void> = $ReadOnly<{
@@ -77,6 +95,8 @@ export type Options<TSplitCondition = void> = $ReadOnly<{
77
95
  allowOptionalDependencies: AllowOptionalDependencies,
78
96
  dependencyRegistry?: ModuleDependencyRegistry<TSplitCondition>,
79
97
  dependencyTransformer?: DependencyTransformer<TSplitCondition>,
98
+ /** Enable `require.context` statements which can be used to import multiple files in a directory. */
99
+ unstable_allowRequireContext: boolean,
80
100
  }>;
81
101
 
82
102
  export type CollectedDependencies<+TSplitCondition> = $ReadOnly<{
@@ -87,8 +107,8 @@ export type CollectedDependencies<+TSplitCondition> = $ReadOnly<{
87
107
 
88
108
  // Registry for the dependency of a module.
89
109
  // Defines when dependencies should be collapsed.
90
- // E.g. should a module that's once required optinally and once not
91
- // be tretaed as the smae or different dependencies.
110
+ // E.g. should a module that's once required optionally and once not
111
+ // be treated as the same or different dependencies.
92
112
  export interface ModuleDependencyRegistry<+TSplitCondition> {
93
113
  registerDependency(
94
114
  qualifier: ImportQualifier,
@@ -151,6 +171,7 @@ function collectDependencies<TSplitCondition = void>(
151
171
  dynamicRequires: options.dynamicRequires,
152
172
  keepRequireNames: options.keepRequireNames,
153
173
  allowOptionalDependencies: options.allowOptionalDependencies,
174
+ unstable_allowRequireContext: options.unstable_allowRequireContext,
154
175
  };
155
176
 
156
177
  const visitor = {
@@ -199,6 +220,26 @@ function collectDependencies<TSplitCondition = void>(
199
220
  return;
200
221
  }
201
222
 
223
+ // Match `require.context`
224
+ if (
225
+ // Feature gate, defaults to `false`.
226
+ state.unstable_allowRequireContext &&
227
+ callee.type === 'MemberExpression' &&
228
+ // `require`
229
+ callee.object.type === 'Identifier' &&
230
+ callee.object.name === 'require' &&
231
+ // `context`
232
+ callee.property.type === 'Identifier' &&
233
+ callee.property.name === 'context' &&
234
+ !callee.computed &&
235
+ // Ensure `require` refers to the global and not something else.
236
+ !path.scope.getBinding('require')
237
+ ) {
238
+ processRequireContextCall(path, state);
239
+ visited.add(path.node);
240
+ return;
241
+ }
242
+
202
243
  if (
203
244
  name != null &&
204
245
  state.dependencyCalls.has(name) &&
@@ -251,6 +292,132 @@ function collectDependencies<TSplitCondition = void>(
251
292
  };
252
293
  }
253
294
 
295
+ /** Extract args passed to the `require.context` method. */
296
+ function getRequireContextArgs(
297
+ path: NodePath<CallExpression>,
298
+ ): [string, RequireContextParams] {
299
+ const args = path.get('arguments');
300
+
301
+ let directory: string;
302
+ if (!Array.isArray(args) || args.length < 1) {
303
+ throw new InvalidRequireCallError(path);
304
+ } else {
305
+ const result = args[0].evaluate();
306
+ if (result.confident && typeof result.value === 'string') {
307
+ directory = result.value;
308
+ } else {
309
+ throw new InvalidRequireCallError(
310
+ result.deopt ?? args[0],
311
+ 'First argument of `require.context` should be a string denoting the directory to require.',
312
+ );
313
+ }
314
+ }
315
+
316
+ // Default to requiring through all directories.
317
+ let recursive: boolean = true;
318
+ if (args.length > 1) {
319
+ const result = args[1].evaluate();
320
+ if (result.confident && typeof result.value === 'boolean') {
321
+ recursive = result.value;
322
+ } else if (!(result.confident && typeof result.value === 'undefined')) {
323
+ throw new InvalidRequireCallError(
324
+ result.deopt ?? args[1],
325
+ 'Second argument of `require.context` should be an optional boolean indicating if files should be imported recursively or not.',
326
+ );
327
+ }
328
+ }
329
+
330
+ // Default to all files.
331
+ let filter: ContextFilter = {pattern: '.*', flags: ''};
332
+ if (args.length > 2) {
333
+ // evaluate() to check for undefined (because it's technically a scope lookup)
334
+ // but check the AST for the regex literal, since evaluate() doesn't do regex.
335
+ const result = args[2].evaluate();
336
+ const argNode = args[2].node;
337
+ if (argNode.type === 'RegExpLiteral') {
338
+ // TODO: Handle `new RegExp(...)` -- `argNode.type === 'NewExpression'`
339
+ filter = {
340
+ pattern: argNode.pattern,
341
+ flags: argNode.flags || '',
342
+ };
343
+ } else if (!(result.confident && typeof result.value === 'undefined')) {
344
+ throw new InvalidRequireCallError(
345
+ args[2],
346
+ `Third argument of \`require.context\` should be an optional RegExp pattern matching all of the files to import, instead found node of type: ${argNode.type}.`,
347
+ );
348
+ }
349
+ }
350
+
351
+ // Default to `sync`.
352
+ let mode: ContextMode = 'sync';
353
+ if (args.length > 3) {
354
+ const result = args[3].evaluate();
355
+ if (result.confident && typeof result.value === 'string') {
356
+ mode = getContextMode(args[3], result.value);
357
+ } else if (!(result.confident && typeof result.value === 'undefined')) {
358
+ throw new InvalidRequireCallError(
359
+ result.deopt ?? args[3],
360
+ 'Fourth argument of `require.context` should be an optional string "mode" denoting how the modules will be resolved.',
361
+ );
362
+ }
363
+ }
364
+
365
+ if (args.length > 4) {
366
+ throw new InvalidRequireCallError(
367
+ path,
368
+ `Too many arguments provided to \`require.context\` call. Expected 4, got: ${args.length}`,
369
+ );
370
+ }
371
+
372
+ return [
373
+ directory,
374
+ {
375
+ recursive,
376
+ filter,
377
+ mode,
378
+ },
379
+ ];
380
+ }
381
+
382
+ function getContextMode(path: NodePath<>, mode: string): ContextMode {
383
+ if (
384
+ mode === 'sync' ||
385
+ mode === 'eager' ||
386
+ mode === 'lazy' ||
387
+ mode === 'lazy-once'
388
+ ) {
389
+ return mode;
390
+ }
391
+ throw new InvalidRequireCallError(
392
+ path,
393
+ `require.context "${mode}" mode is not supported. Expected one of: sync, eager, lazy, lazy-once`,
394
+ );
395
+ }
396
+
397
+ function processRequireContextCall<TSplitCondition>(
398
+ path: NodePath<CallExpression>,
399
+ state: State<TSplitCondition>,
400
+ ): void {
401
+ const [directory, contextParams] = getRequireContextArgs(path);
402
+ const transformer = state.dependencyTransformer;
403
+ const dep = registerDependency(
404
+ state,
405
+ {
406
+ // We basically want to "import" every file in a folder and then filter them out with the given `filter` RegExp.
407
+ name: directory,
408
+ // Capture the matching context
409
+ contextParams,
410
+ asyncType: null,
411
+ optional: isOptionalDependency(directory, path, state),
412
+ },
413
+ path,
414
+ );
415
+
416
+ // require() the generated module representing this context
417
+ path.get('callee').replaceWith(types.identifier('require'));
418
+ transformer.transformSyncRequire(path, dep, state);
419
+ }
420
+
254
421
  function collectImports<TSplitCondition>(
255
422
  path: NodePath<>,
256
423
  state: State<TSplitCondition>,
@@ -332,7 +499,7 @@ function processRequireCall<TSplitCondition>(
332
499
  }
333
500
 
334
501
  function getNearestLocFromPath(path: NodePath<>): ?BabelSourceLocation {
335
- let current = path;
502
+ let current: ?(NodePath<> | NodePath<BabelNode>) = path;
336
503
  while (current && !current.node.loc) {
337
504
  current = current.parentPath;
338
505
  }
@@ -344,6 +511,7 @@ export type ImportQualifier = $ReadOnly<{
344
511
  asyncType: AsyncDependencyType | null,
345
512
  splitCondition?: NodePath<>,
346
513
  optional: boolean,
514
+ contextParams?: RequireContextParams,
347
515
  }>;
348
516
 
349
517
  function registerDependency<TSplitCondition>(
@@ -352,7 +520,6 @@ function registerDependency<TSplitCondition>(
352
520
  path: NodePath<>,
353
521
  ): InternalDependency<TSplitCondition> {
354
522
  const dependency = state.dependencyRegistry.registerDependency(qualifier);
355
-
356
523
  const loc = getNearestLocFromPath(path);
357
524
  if (loc != null) {
358
525
  dependency.locs.push(loc);
@@ -383,7 +550,7 @@ function isOptionalDependency<TSplitCondition>(
383
550
 
384
551
  // Valid statement stack for single-level try-block: expressionStatement -> blockStatement -> tryStatement
385
552
  let sCount = 0;
386
- let p = path;
553
+ let p: ?(NodePath<> | NodePath<BabelNode>) = path;
387
554
  while (p && sCount < 3) {
388
555
  if (p.isStatement()) {
389
556
  if (p.node.type === 'BlockStatement') {
@@ -419,14 +586,20 @@ function getModuleNameFromCallArgs(path: NodePath<CallExpression>): ?string {
419
586
 
420
587
  return null;
421
588
  }
589
+
422
590
  collectDependencies.getModuleNameFromCallArgs = getModuleNameFromCallArgs;
423
591
 
424
592
  class InvalidRequireCallError extends Error {
425
- constructor({node}: any) {
593
+ constructor({node}: NodePath<>, message?: string) {
426
594
  const line = node.loc && node.loc.start && node.loc.start.line;
427
595
 
428
596
  super(
429
- `Invalid call at line ${line || '<unknown>'}: ${generate(node).code}`,
597
+ [
598
+ `Invalid call at line ${line || '<unknown>'}: ${generate(node).code}`,
599
+ message,
600
+ ]
601
+ .filter(Boolean)
602
+ .join('\n'),
430
603
  );
431
604
  }
432
605
  }
@@ -469,9 +642,11 @@ const DefaultDependencyTransformer: DependencyTransformer<mixed> = {
469
642
  state: State<mixed>,
470
643
  ): void {
471
644
  const moduleIDExpression = createModuleIDExpression(dependency, state);
472
- path.node.arguments = state.keepRequireNames
473
- ? [moduleIDExpression, types.stringLiteral(dependency.name)]
474
- : [moduleIDExpression];
645
+ path.node.arguments = [moduleIDExpression];
646
+ // Always add the debug name argument last
647
+ if (state.keepRequireNames) {
648
+ path.node.arguments.push(types.stringLiteral(dependency.name));
649
+ }
475
650
  },
476
651
 
477
652
  transformImportCall(
@@ -546,6 +721,44 @@ function createModuleNameLiteral(dependency: InternalDependency<mixed>) {
546
721
  return types.stringLiteral(dependency.name);
547
722
  }
548
723
 
724
+ /**
725
+ * Given an import qualifier, return a key used to register the dependency.
726
+ * Generally this return the `ImportQualifier.name` property, but in the case
727
+ * of `require.context` more attributes can be appended to distinguish various combinations that would otherwise conflict.
728
+ *
729
+ * For example, the following case would have collision issues if they all utilized the `name` property:
730
+ * ```
731
+ * require('./foo');
732
+ * require.context('./foo');
733
+ * require.context('./foo', true, /something/);
734
+ * require.context('./foo', false, /something/);
735
+ * require.context('./foo', false, /something/, 'lazy');
736
+ * ```
737
+ *
738
+ * This method should be utilized by `registerDependency`.
739
+ */
740
+ function getKeyForDependency(qualifier: ImportQualifier): string {
741
+ let key = qualifier.name;
742
+
743
+ const {contextParams} = qualifier;
744
+ // Add extra qualifiers when using `require.context` to prevent collisions.
745
+ if (contextParams) {
746
+ // NOTE(EvanBacon): Keep this synchronized with `RequireContextParams`, if any other properties are added
747
+ // then this key algorithm should be updated to account for those properties.
748
+ // Example: `./directory__true__/foobar/m__lazy`
749
+ key += [
750
+ '',
751
+ 'context',
752
+ String(contextParams.recursive),
753
+ String(contextParams.filter.pattern),
754
+ String(contextParams.filter.flags),
755
+ contextParams.mode,
756
+ // Join together and append to the name:
757
+ ].join('__');
758
+ }
759
+ return key;
760
+ }
761
+
549
762
  class DefaultModuleDependencyRegistry<TSplitCondition = void>
550
763
  implements ModuleDependencyRegistry<TSplitCondition>
551
764
  {
@@ -554,8 +767,9 @@ class DefaultModuleDependencyRegistry<TSplitCondition = void>
554
767
  registerDependency(
555
768
  qualifier: ImportQualifier,
556
769
  ): InternalDependency<TSplitCondition> {
770
+ const key = getKeyForDependency(qualifier);
557
771
  let dependency: ?InternalDependency<TSplitCondition> =
558
- this._dependencies.get(qualifier.name);
772
+ this._dependencies.get(key);
559
773
 
560
774
  if (dependency == null) {
561
775
  const newDependency: MutableInternalDependency<TSplitCondition> = {
@@ -568,14 +782,17 @@ class DefaultModuleDependencyRegistry<TSplitCondition = void>
568
782
  if (qualifier.optional) {
569
783
  newDependency.isOptional = true;
570
784
  }
785
+ if (qualifier.contextParams) {
786
+ newDependency.contextParams = qualifier.contextParams;
787
+ }
571
788
 
572
789
  dependency = newDependency;
573
- this._dependencies.set(qualifier.name, dependency);
790
+ this._dependencies.set(key, dependency);
574
791
  } else {
575
792
  const original = dependency;
576
793
  dependency = collapseDependencies(original, qualifier);
577
794
  if (original !== dependency) {
578
- this._dependencies.set(qualifier.name, dependency);
795
+ this._dependencies.set(key, dependency);
579
796
  }
580
797
  }
581
798
 
@@ -35,7 +35,7 @@ export type StackFrameOutput = $ReadOnly<{
35
35
  ...
36
36
  }>;
37
37
  type ExplodedSourceMapModule = $ElementType<ExplodedSourceMap, number>;
38
- type Position = {|+line1Based: number, column0Based: number|};
38
+ type Position = {+line1Based: number, column0Based: number};
39
39
 
40
40
  function createFunctionNameGetter(
41
41
  module: ExplodedSourceMapModule,
@@ -81,7 +81,7 @@ export type BundleMetadata = {
81
81
  ...
82
82
  };
83
83
 
84
- type ProcessStartContext = {|
84
+ type ProcessStartContext = {
85
85
  +buildID: string,
86
86
  +bundleOptions: BundleOptions,
87
87
  +graphId: GraphId,
@@ -91,24 +91,24 @@ type ProcessStartContext = {|
91
91
  +req: IncomingMessage,
92
92
  +revisionId?: ?RevisionId,
93
93
  ...SplitBundleOptions,
94
- |};
94
+ };
95
95
 
96
- type ProcessDeleteContext = {|
96
+ type ProcessDeleteContext = {
97
97
  +graphId: GraphId,
98
98
  +req: IncomingMessage,
99
99
  +res: ServerResponse,
100
- |};
100
+ };
101
101
 
102
- type ProcessEndContext<T> = {|
102
+ type ProcessEndContext<T> = {
103
103
  ...ProcessStartContext,
104
104
  +result: T,
105
- |};
105
+ };
106
106
 
107
- export type ServerOptions = $ReadOnly<{|
107
+ export type ServerOptions = $ReadOnly<{
108
108
  hasReducedPerformance?: boolean,
109
109
  onBundleBuilt?: (bundlePath: string) => void,
110
110
  watch?: boolean,
111
- |}>;
111
+ }>;
112
112
 
113
113
  const DELTA_ID_HEADER = 'X-Metro-Delta-ID';
114
114
  const FILES_CHANGED_COUNT_HEADER = 'X-Metro-Files-Changed-Count';
@@ -504,7 +504,7 @@ class Server {
504
504
  build,
505
505
  delete: deleteFn,
506
506
  finish,
507
- }: {|
507
+ }: {
508
508
  +createStartEntry: (context: ProcessStartContext) => ActionLogEntryData,
509
509
  +createEndEntry: (
510
510
  context: ProcessEndContext<T>,
@@ -512,7 +512,7 @@ class Server {
512
512
  +build: (context: ProcessStartContext) => Promise<T>,
513
513
  +delete?: (context: ProcessDeleteContext) => Promise<void>,
514
514
  +finish: (context: ProcessEndContext<T>) => void,
515
- |}) {
515
+ }) {
516
516
  return async function requestProcessor(
517
517
  req: IncomingMessage,
518
518
  res: ServerResponse,
@@ -703,12 +703,12 @@ class Server {
703
703
  };
704
704
  },
705
705
  createEndEntry(
706
- context: ProcessEndContext<{|
706
+ context: ProcessEndContext<{
707
707
  bundle: string,
708
708
  lastModifiedDate: Date,
709
709
  nextRevId: RevisionId,
710
710
  numModifiedFiles: number,
711
- |}>,
711
+ }>,
712
712
  ) {
713
713
  return {
714
714
  outdated_modules: context.result.numModifiedFiles,
@@ -820,12 +820,12 @@ class Server {
820
820
  };
821
821
  },
822
822
  createEndEntry(
823
- context: ProcessEndContext<{|
823
+ context: ProcessEndContext<{
824
824
  bytecode: Buffer,
825
825
  lastModifiedDate: Date,
826
826
  nextRevId: RevisionId,
827
827
  numModifiedFiles: number,
828
- |}>,
828
+ }>,
829
829
  ) {
830
830
  return {
831
831
  outdated_modules: context.result.numModifiedFiles,
@@ -1193,14 +1193,14 @@ class Server {
1193
1193
  return this._config.watchFolders;
1194
1194
  }
1195
1195
 
1196
- static DEFAULT_GRAPH_OPTIONS: {|
1196
+ static DEFAULT_GRAPH_OPTIONS: {
1197
1197
  customTransformOptions: any,
1198
1198
  dev: boolean,
1199
1199
  hot: boolean,
1200
1200
  minify: boolean,
1201
1201
  runtimeBytecodeVersion: ?number,
1202
1202
  unstable_transformProfile: 'default',
1203
- |} = {
1203
+ } = {
1204
1204
  customTransformOptions: Object.create(null),
1205
1205
  dev: true,
1206
1206
  hot: false,
@@ -1209,7 +1209,7 @@ class Server {
1209
1209
  unstable_transformProfile: 'default',
1210
1210
  };
1211
1211
 
1212
- static DEFAULT_BUNDLE_OPTIONS: {|
1212
+ static DEFAULT_BUNDLE_OPTIONS: {
1213
1213
  ...typeof Server.DEFAULT_GRAPH_OPTIONS,
1214
1214
  excludeSource: false,
1215
1215
  inlineSourceMap: false,
@@ -1219,7 +1219,7 @@ class Server {
1219
1219
  shallow: false,
1220
1220
  sourceMapUrl: null,
1221
1221
  sourceUrl: null,
1222
- |} = {
1222
+ } = {
1223
1223
  ...Server.DEFAULT_GRAPH_OPTIONS,
1224
1224
  excludeSource: false,
1225
1225
  inlineSourceMap: false,
package/src/cli.js CHANGED
@@ -11,6 +11,11 @@
11
11
  */
12
12
  "use strict";
13
13
 
14
+ try {
15
+ // $FlowFixMe[untyped-import]
16
+ require("metro-babel-register").unstable_registerForMetroMonorepo();
17
+ } catch {}
18
+
14
19
  const { attachMetroCli } = require("./index");
15
20
 
16
21
  const yargs = require("yargs");
package/src/cli.js.flow CHANGED
@@ -11,6 +11,11 @@
11
11
 
12
12
  'use strict';
13
13
 
14
+ try {
15
+ // $FlowFixMe[untyped-import]
16
+ require('metro-babel-register').unstable_registerForMetroMonorepo();
17
+ } catch {}
18
+
14
19
  const {attachMetroCli} = require('./index');
15
20
  const yargs = require('yargs');
16
21
 
@@ -11,8 +11,6 @@
11
11
 
12
12
  const { makeAsyncCommand } = require("../cli-utils");
13
13
 
14
- const MetroApi = require("../index");
15
-
16
14
  const TerminalReporter = require("../lib/TerminalReporter");
17
15
 
18
16
  const { loadConfig } = require("metro-config");
@@ -78,7 +76,10 @@ module.exports = () => ({
78
76
  handler: makeAsyncCommand(async (argv) => {
79
77
  const config = await loadConfig(argv); // $FlowExpectedError YargArguments and RunBuildOptions are used interchangeable but their types are not yet compatible
80
78
 
81
- const options = argv;
79
+ const options = argv; // Inline require() to avoid circular dependency with ../index
80
+
81
+ const MetroApi = require("../index");
82
+
82
83
  await MetroApi.runBuild(config, {
83
84
  ...options,
84
85
  onBegin: () => {
@@ -15,7 +15,6 @@ import type {YargArguments} from 'metro-config/src/configTypes.flow';
15
15
  import typeof Yargs from 'yargs';
16
16
 
17
17
  const {makeAsyncCommand} = require('../cli-utils');
18
- const MetroApi = require('../index');
19
18
  const TerminalReporter = require('../lib/TerminalReporter');
20
19
  const {loadConfig} = require('metro-config');
21
20
  const {Terminal} = require('metro-core');
@@ -23,12 +22,12 @@ const {Terminal} = require('metro-core');
23
22
  const term = new Terminal(process.stdout);
24
23
  const updateReporter = new TerminalReporter(term);
25
24
 
26
- module.exports = (): ({|
25
+ module.exports = (): ({
27
26
  builder: (yargs: Yargs) => void,
28
27
  command: string,
29
28
  description: string,
30
29
  handler: (argv: YargArguments) => void,
31
- |}) => ({
30
+ }) => ({
32
31
  command: 'build <entry>',
33
32
 
34
33
  description:
@@ -66,6 +65,9 @@ module.exports = (): ({|
66
65
  // $FlowExpectedError YargArguments and RunBuildOptions are used interchangeable but their types are not yet compatible
67
66
  const options = (argv: RunBuildOptions);
68
67
 
68
+ // Inline require() to avoid circular dependency with ../index
69
+ const MetroApi = require('../index');
70
+
69
71
  await MetroApi.runBuild(config, {
70
72
  ...options,
71
73
  onBegin: (): void => {
@@ -11,8 +11,6 @@
11
11
 
12
12
  const { makeAsyncCommand, watchFile } = require("../cli-utils");
13
13
 
14
- const MetroApi = require("../index");
15
-
16
14
  const { loadConfig, resolveConfig } = require("metro-config");
17
15
 
18
16
  const { promisify } = require("util");
@@ -93,7 +91,9 @@ module.exports = () => ({
93
91
  await promisify(server.close).call(server);
94
92
  }
95
93
 
96
- const config = await loadConfig(argv); // $FlowExpectedError YargArguments and RunBuildOptions are used interchangeable but their types are not yet compatible
94
+ const config = await loadConfig(argv); // Inline require() to avoid circular dependency with ../index
95
+
96
+ const MetroApi = require("../index"); // $FlowExpectedError YargArguments and RunBuildOptions are used interchangeable but their types are not yet compatible
97
97
 
98
98
  server = await MetroApi.runServer(config, argv);
99
99
  restarting = false;
@@ -15,16 +15,15 @@ import type {YargArguments} from 'metro-config/src/configTypes.flow';
15
15
  import typeof Yargs from 'yargs';
16
16
 
17
17
  const {makeAsyncCommand, watchFile} = require('../cli-utils');
18
- const MetroApi = require('../index');
19
18
  const {loadConfig, resolveConfig} = require('metro-config');
20
19
  const {promisify} = require('util');
21
20
 
22
- module.exports = (): ({|
21
+ module.exports = (): ({
23
22
  builder: (yargs: Yargs) => void,
24
23
  command: $TEMPORARY$string<'serve'>,
25
24
  description: string,
26
25
  handler: (argv: YargArguments) => void,
27
- |}) => ({
26
+ }) => ({
28
27
  command: 'serve',
29
28
 
30
29
  description: 'Starts Metro on the given port, building bundles on the fly',
@@ -84,6 +83,9 @@ module.exports = (): ({|
84
83
 
85
84
  const config = await loadConfig(argv);
86
85
 
86
+ // Inline require() to avoid circular dependency with ../index
87
+ const MetroApi = require('../index');
88
+
87
89
  // $FlowExpectedError YargArguments and RunBuildOptions are used interchangeable but their types are not yet compatible
88
90
  server = await MetroApi.runServer(config, (argv: RunServerOptions));
89
91