metro 0.82.2 → 0.82.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metro",
3
- "version": "0.82.2",
3
+ "version": "0.82.4",
4
4
  "description": "🚇 The JavaScript bundler for React Native.",
5
5
  "main": "src/index.js",
6
6
  "bin": "src/cli.js",
@@ -42,18 +42,18 @@
42
42
  "jest-worker": "^29.7.0",
43
43
  "jsc-safe-url": "^0.2.2",
44
44
  "lodash.throttle": "^4.1.1",
45
- "metro-babel-transformer": "0.82.2",
46
- "metro-cache": "0.82.2",
47
- "metro-cache-key": "0.82.2",
48
- "metro-config": "0.82.2",
49
- "metro-core": "0.82.2",
50
- "metro-file-map": "0.82.2",
51
- "metro-resolver": "0.82.2",
52
- "metro-runtime": "0.82.2",
53
- "metro-source-map": "0.82.2",
54
- "metro-symbolicate": "0.82.2",
55
- "metro-transform-plugins": "0.82.2",
56
- "metro-transform-worker": "0.82.2",
45
+ "metro-babel-transformer": "0.82.4",
46
+ "metro-cache": "0.82.4",
47
+ "metro-cache-key": "0.82.4",
48
+ "metro-config": "0.82.4",
49
+ "metro-core": "0.82.4",
50
+ "metro-file-map": "0.82.4",
51
+ "metro-resolver": "0.82.4",
52
+ "metro-runtime": "0.82.4",
53
+ "metro-source-map": "0.82.4",
54
+ "metro-symbolicate": "0.82.4",
55
+ "metro-transform-plugins": "0.82.4",
56
+ "metro-transform-worker": "0.82.4",
57
57
  "mime-types": "^2.1.27",
58
58
  "nullthrows": "^1.1.1",
59
59
  "serialize-error": "^2.1.0",
@@ -65,14 +65,15 @@
65
65
  "devDependencies": {
66
66
  "@babel/plugin-transform-flow-strip-types": "^7.25.2",
67
67
  "@babel/plugin-transform-modules-commonjs": "^7.24.8",
68
+ "@babel/plugin-transform-runtime": "^7.24.7",
68
69
  "@react-native/babel-preset": "0.78.0",
69
70
  "@react-native/metro-babel-transformer": "0.78.0",
70
71
  "babel-jest": "^29.7.0",
71
72
  "dedent": "^0.7.0",
72
73
  "jest-snapshot": "^29.7.0",
73
74
  "jest-snapshot-serializer-raw": "^1.2.0",
74
- "metro-babel-register": "0.82.2",
75
- "metro-memory-fs": "0.82.2",
75
+ "metro-babel-register": "0.82.4",
76
+ "metro-memory-fs": "0.82.4",
76
77
  "mock-req": "^0.2.0",
77
78
  "mock-res": "^0.6.0",
78
79
  "stack-trace": "^0.0.10"
@@ -14,7 +14,7 @@
14
14
  import type {TransformResultWithSource} from './DeltaBundler';
15
15
  import type {TransformOptions} from './DeltaBundler/Worker';
16
16
  import type EventEmitter from 'events';
17
- import type {ConfigT} from 'metro-config/src/configTypes.flow';
17
+ import type {ConfigT} from 'metro-config';
18
18
 
19
19
  const Transformer = require('./DeltaBundler/Transformer');
20
20
  const DependencyGraph = require('./node-haste/DependencyGraph');
@@ -17,7 +17,7 @@ import type {
17
17
  } from '../../shared/types.flow';
18
18
  import type {Module, ReadOnlyGraph, SerializerOptions} from '../types.flow';
19
19
  import type {SourceMapGeneratorOptions} from './sourceMapGenerator';
20
- import type {GetTransformOptions} from 'metro-config/src/configTypes.flow.js';
20
+ import type {GetTransformOptions} from 'metro-config';
21
21
 
22
22
  const {createRamBundleGroups} = require('../../Bundler/util');
23
23
  const getAppendScripts = require('../../lib/getAppendScripts');
@@ -7,6 +7,7 @@ function _interopRequireDefault(e) {
7
7
  const getTransformCacheKey = require("./getTransformCacheKey");
8
8
  const WorkerFarm = require("./WorkerFarm");
9
9
  const assert = require("assert");
10
+ const debug = require("debug")("Metro:Transformer");
10
11
  const fs = require("fs");
11
12
  const { Cache, stableHash } = require("metro-cache");
12
13
  const path = require("path");
@@ -35,7 +36,9 @@ class Transformer {
35
36
  projectRoot: this._config.projectRoot,
36
37
  transformerConfig: transformerOptions,
37
38
  });
38
- this._baseHash = stableHash([globalCacheKey]).toString("binary");
39
+ const baseHashBuffer = stableHash([globalCacheKey]);
40
+ this._baseHash = baseHashBuffer.toString("binary");
41
+ debug("Base hash: %s", baseHashBuffer.toString("hex"));
39
42
  }
40
43
  async transformFile(filePath, transformerOptions, fileBuffer) {
41
44
  const cache = this._cache;
@@ -13,13 +13,14 @@
13
13
 
14
14
  import type {TransformResult, TransformResultWithSource} from '../DeltaBundler';
15
15
  import type {TransformerConfig, TransformOptions} from './Worker';
16
- import type {ConfigT} from 'metro-config/src/configTypes.flow';
16
+ import type {ConfigT} from 'metro-config';
17
17
 
18
18
  import crypto from 'crypto';
19
19
 
20
20
  const getTransformCacheKey = require('./getTransformCacheKey');
21
21
  const WorkerFarm = require('./WorkerFarm');
22
22
  const assert = require('assert');
23
+ const debug = require('debug')('Metro:Transformer');
23
24
  const fs = require('fs');
24
25
  const {Cache, stableHash} = require('metro-cache');
25
26
  const path = require('path');
@@ -69,7 +70,9 @@ class Transformer {
69
70
  transformerConfig: transformerOptions,
70
71
  });
71
72
 
72
- this._baseHash = stableHash([globalCacheKey]).toString('binary');
73
+ const baseHashBuffer = stableHash([globalCacheKey]);
74
+ this._baseHash = baseHashBuffer.toString('binary');
75
+ debug('Base hash: %s', baseHashBuffer.toString('hex'));
73
76
  }
74
77
 
75
78
  async transformFile(
@@ -13,7 +13,7 @@
13
13
 
14
14
  import type {TransformResult} from '../DeltaBundler';
15
15
  import type {TransformerConfig, TransformOptions, Worker} from './Worker';
16
- import type {ConfigT} from 'metro-config/src/configTypes.flow';
16
+ import type {ConfigT} from 'metro-config';
17
17
  import type {Readable} from 'stream';
18
18
 
19
19
  const {Worker: JestWorker} = require('jest-worker');
@@ -151,6 +151,7 @@ class WorkerFarm {
151
151
  _formatGenericError(err: any, filename: string): TransformError {
152
152
  const error = new TransformError(`${filename}: ${err.message}`);
153
153
 
154
+ // $FlowFixMe[unsafe-object-assign]
154
155
  return Object.assign(error, {
155
156
  stack: (err.stack || '').split('\n').slice(0, -1).join('\n'),
156
157
  lineNumber: 0,
package/src/HmrServer.js CHANGED
@@ -35,7 +35,7 @@ class HmrServer {
35
35
  async _registerEntryPoint(client, requestUrl, sendFn) {
36
36
  requestUrl = this._config.server.rewriteRequestUrl(requestUrl);
37
37
  const clientUrl = nullthrows(url.parse(requestUrl, true));
38
- const options = parseOptionsFromUrl(
38
+ const { bundleType: _bundleType, ...options } = parseOptionsFromUrl(
39
39
  requestUrl,
40
40
  new Set(this._config.resolver.platforms)
41
41
  );
@@ -101,7 +101,7 @@ class HmrServer<TClient: Client> {
101
101
  ): Promise<void> {
102
102
  requestUrl = this._config.server.rewriteRequestUrl(requestUrl);
103
103
  const clientUrl = nullthrows(url.parse(requestUrl, true));
104
- const options = parseOptionsFromUrl(
104
+ const {bundleType: _bundleType, ...options} = parseOptionsFromUrl(
105
105
  requestUrl,
106
106
  new Set(this._config.resolver.platforms),
107
107
  );
@@ -19,7 +19,7 @@ import type {
19
19
  } from './DeltaBundler/types.flow';
20
20
  import type {GraphId} from './lib/getGraphId';
21
21
  import type {ResolverInputOptions} from './shared/types.flow';
22
- import type {ConfigT} from 'metro-config/src/configTypes.flow';
22
+ import type {ConfigT} from 'metro-config';
23
23
 
24
24
  const Bundler = require('./Bundler');
25
25
  const DeltaBundler = require('./DeltaBundler');
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
+ var _types = require("@babel/types");
3
4
  const generate = require("@babel/generator").default;
4
5
  const template = require("@babel/template").default;
5
6
  const traverse = require("@babel/traverse").default;
@@ -346,6 +347,9 @@ function getNearestLocFromPath(path) {
346
347
  ) {
347
348
  current = current.parentPath;
348
349
  }
350
+ if (current && (0, _types.isProgram)(current.node)) {
351
+ current = null;
352
+ }
349
353
  return current?.node.METRO_INLINE_REQUIRES_INIT_LOC ?? current?.node.loc;
350
354
  }
351
355
  function registerDependency(state, qualifier, path) {
@@ -17,6 +17,8 @@ import type {
17
17
  AsyncDependencyType,
18
18
  } from 'metro/src/DeltaBundler/types.flow.js';
19
19
 
20
+ import {isProgram} from '@babel/types';
21
+
20
22
  const generate = require('@babel/generator').default;
21
23
  const template = require('@babel/template').default;
22
24
  const traverse = require('@babel/traverse').default;
@@ -575,6 +577,10 @@ function getNearestLocFromPath(path: NodePath<>): ?BabelSourceLocation {
575
577
  ) {
576
578
  current = current.parentPath;
577
579
  }
580
+ // Do not use the location of the `Program` node
581
+ if (current && isProgram(current.node)) {
582
+ current = null;
583
+ }
578
584
  return (
579
585
  // $FlowIgnore[prop-missing] METRO_INLINE_REQUIRES_INIT_LOC is Metro-specific and not typed
580
586
  current?.node.METRO_INLINE_REQUIRES_INIT_LOC ?? current?.node.loc
@@ -1,16 +1,14 @@
1
1
  "use strict";
2
2
 
3
- const invariant = require("invariant");
4
3
  function importLocationsPlugin({ types: t }) {
5
- const importDeclarationLocs = new Set();
6
4
  return {
7
5
  visitor: {
8
- ImportDeclaration(path) {
6
+ ImportDeclaration(path, { importDeclarationLocs }) {
9
7
  if (path.node.importKind !== "type" && path.node.loc != null) {
10
8
  importDeclarationLocs.add(locToKey(path.node.loc));
11
9
  }
12
10
  },
13
- ExportDeclaration(path) {
11
+ ExportDeclaration(path, { importDeclarationLocs }) {
14
12
  if (
15
13
  path.node.source != null &&
16
14
  path.node.exportKind !== "type" &&
@@ -19,21 +17,18 @@ function importLocationsPlugin({ types: t }) {
19
17
  importDeclarationLocs.add(locToKey(path.node.loc));
20
18
  }
21
19
  },
22
- },
23
- pre: ({ path, metadata }) => {
24
- invariant(
25
- path && t.isProgram(path.node),
26
- "path missing or not a program node"
27
- );
28
- const metroMetadata = metadata;
29
- if (!metroMetadata.metro) {
30
- metroMetadata.metro = {
31
- unstable_importDeclarationLocs: importDeclarationLocs,
32
- };
33
- } else {
34
- metroMetadata.metro.unstable_importDeclarationLocs =
35
- importDeclarationLocs;
36
- }
20
+ Program(path, state) {
21
+ state.importDeclarationLocs = new Set();
22
+ const metroMetadata = state.file.metadata;
23
+ if (!metroMetadata.metro) {
24
+ metroMetadata.metro = {
25
+ unstable_importDeclarationLocs: state.importDeclarationLocs,
26
+ };
27
+ } else {
28
+ metroMetadata.metro.unstable_importDeclarationLocs =
29
+ state.importDeclarationLocs;
30
+ }
31
+ },
37
32
  },
38
33
  };
39
34
  }
@@ -11,19 +11,27 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- import type {PluginObj} from '@babel/core';
14
+ import type {File, PluginObj} from '@babel/core';
15
15
  import typeof * as Types from '@babel/types';
16
16
  import type {MetroBabelFileMetadata} from 'metro-babel-transformer';
17
17
 
18
- const invariant = require('invariant');
19
-
20
18
  type ImportDeclarationLocs = Set<string>;
21
19
 
22
- function importLocationsPlugin({types: t}: {types: Types, ...}): PluginObj<> {
23
- const importDeclarationLocs: ImportDeclarationLocs = new Set();
20
+ type State = {
21
+ importDeclarationLocs: ImportDeclarationLocs,
22
+ file: File,
23
+ ...
24
+ };
25
+
26
+ function importLocationsPlugin({
27
+ types: t,
28
+ }: {
29
+ types: Types,
30
+ ...
31
+ }): PluginObj<State> {
24
32
  return {
25
33
  visitor: {
26
- ImportDeclaration(path) {
34
+ ImportDeclaration(path, {importDeclarationLocs}) {
27
35
  if (
28
36
  // Ignore type imports
29
37
  path.node.importKind !== 'type' &&
@@ -35,7 +43,7 @@ function importLocationsPlugin({types: t}: {types: Types, ...}): PluginObj<> {
35
43
  importDeclarationLocs.add(locToKey(path.node.loc));
36
44
  }
37
45
  },
38
- ExportDeclaration(path) {
46
+ ExportDeclaration(path, {importDeclarationLocs}) {
39
47
  if (
40
48
  // If `source` is set, this is a re-export, so it declares an ESM
41
49
  // dependency.
@@ -48,25 +56,23 @@ function importLocationsPlugin({types: t}: {types: Types, ...}): PluginObj<> {
48
56
  importDeclarationLocs.add(locToKey(path.node.loc));
49
57
  }
50
58
  },
51
- },
52
- pre: ({path, metadata}) => {
53
- invariant(
54
- path && t.isProgram(path.node),
55
- 'path missing or not a program node',
56
- );
59
+ Program(path, state) {
60
+ // Initialise state
61
+ state.importDeclarationLocs = new Set();
57
62
 
58
- // $FlowFixMe[prop-missing] Babel `File` is not generically typed
59
- const metroMetadata: MetroBabelFileMetadata = metadata;
63
+ // $FlowFixMe[prop-missing] Babel `File` is not generically typed
64
+ const metroMetadata: MetroBabelFileMetadata = state.file.metadata;
60
65
 
61
- // Set the result on a metadata property
62
- if (!metroMetadata.metro) {
63
- metroMetadata.metro = {
64
- unstable_importDeclarationLocs: importDeclarationLocs,
65
- };
66
- } else {
67
- metroMetadata.metro.unstable_importDeclarationLocs =
68
- importDeclarationLocs;
69
- }
66
+ // Set the result on a metadata property
67
+ if (!metroMetadata.metro) {
68
+ metroMetadata.metro = {
69
+ unstable_importDeclarationLocs: state.importDeclarationLocs,
70
+ };
71
+ } else {
72
+ metroMetadata.metro.unstable_importDeclarationLocs =
73
+ state.importDeclarationLocs;
74
+ }
75
+ },
70
76
  },
71
77
  };
72
78
  }
@@ -15,7 +15,7 @@ import type {
15
15
  MetroSourceMapSegmentTuple,
16
16
  } from '../../../metro-source-map/src/source-map';
17
17
  import type {ExplodedSourceMap} from '../DeltaBundler/Serializers/getExplodedSourceMap';
18
- import type {ConfigT} from 'metro-config/src/configTypes.flow';
18
+ import type {ConfigT} from 'metro-config';
19
19
 
20
20
  const {greatestLowerBound} = require('metro-source-map/src/Consumer/search');
21
21
  const {
package/src/Server.js CHANGED
@@ -269,7 +269,6 @@ class Server {
269
269
  splitBundleOptions({
270
270
  ...Server.DEFAULT_BUNDLE_OPTIONS,
271
271
  ...options,
272
- bundleType: "bundle",
273
272
  });
274
273
  const { prepend, graph } = await this._bundler.buildGraph(
275
274
  entryFile,
@@ -358,7 +357,11 @@ class Server {
358
357
  this._processRequest(req, res, next).catch(next);
359
358
  };
360
359
  _parseOptions(url) {
361
- return parseOptionsFromUrl(url, new Set(this._config.resolver.platforms));
360
+ const { bundleType: _bundleType, ...bundleOptions } = parseOptionsFromUrl(
361
+ url,
362
+ new Set(this._config.resolver.platforms)
363
+ );
364
+ return bundleOptions;
362
365
  }
363
366
  _rewriteAndNormalizeUrl(requestUrl) {
364
367
  return jscSafeUrl.toNormalUrl(
@@ -472,6 +475,7 @@ class Server {
472
475
  });
473
476
  }
474
477
  _createRequestProcessor({
478
+ bundleType,
475
479
  createStartEntry,
476
480
  createEndEntry,
477
481
  build,
@@ -571,7 +575,7 @@ class Server {
571
575
  this._reporter.update({
572
576
  buildID: getBuildID(buildNumber),
573
577
  bundleDetails: {
574
- bundleType: bundleOptions.bundleType,
578
+ bundleType,
575
579
  customResolverOptions: bundleOptions.customResolverOptions,
576
580
  customTransformOptions: bundleOptions.customTransformOptions,
577
581
  dev: transformOptions.dev,
@@ -649,6 +653,7 @@ class Server {
649
653
  };
650
654
  }
651
655
  _processBundleRequest = this._createRequestProcessor({
656
+ bundleType: "bundle",
652
657
  createStartEntry(context) {
653
658
  return {
654
659
  action_name: "Requesting bundle",
@@ -827,6 +832,7 @@ class Server {
827
832
  );
828
833
  }
829
834
  _processSourceMapRequest = this._createRequestProcessor({
835
+ bundleType: "map",
830
836
  createStartEntry(context) {
831
837
  return {
832
838
  action_name: "Requesting sourcemap",
@@ -890,6 +896,7 @@ class Server {
890
896
  },
891
897
  });
892
898
  _processAssetsRequest = this._createRequestProcessor({
899
+ bundleType: "assets",
893
900
  createStartEntry(context) {
894
901
  return {
895
902
  action_name: "Requesting assets",
@@ -34,7 +34,7 @@ import type {
34
34
  import type {IncomingMessage} from 'connect';
35
35
  import type {ServerResponse} from 'http';
36
36
  import type {CacheStore} from 'metro-cache';
37
- import type {ConfigT, RootPerfLogger} from 'metro-config/src/configTypes.flow';
37
+ import type {ConfigT, RootPerfLogger} from 'metro-config';
38
38
  import type {
39
39
  ActionLogEntryData,
40
40
  ActionStartLogEntry,
@@ -404,7 +404,6 @@ class Server {
404
404
  } = splitBundleOptions({
405
405
  ...Server.DEFAULT_BUNDLE_OPTIONS,
406
406
  ...options,
407
- bundleType: 'bundle',
408
407
  });
409
408
 
410
409
  const {prepend, graph} = await this._bundler.buildGraph(
@@ -469,6 +468,7 @@ class Server {
469
468
  urlObj.query.unstable_path.match(/^([^?]*)\??(.*)$/),
470
469
  );
471
470
  if (secondaryQuery) {
471
+ // $FlowFixMe[unsafe-object-assign]
472
472
  Object.assign(urlObj.query, querystring.parse(secondaryQuery));
473
473
  }
474
474
  assetPath = actualPath;
@@ -524,7 +524,11 @@ class Server {
524
524
  };
525
525
 
526
526
  _parseOptions(url: string): BundleOptions {
527
- return parseOptionsFromUrl(url, new Set(this._config.resolver.platforms));
527
+ const {bundleType: _bundleType, ...bundleOptions} = parseOptionsFromUrl(
528
+ url,
529
+ new Set(this._config.resolver.platforms),
530
+ );
531
+ return bundleOptions;
528
532
  }
529
533
 
530
534
  _rewriteAndNormalizeUrl(requestUrl: string): string {
@@ -652,12 +656,14 @@ class Server {
652
656
  }
653
657
 
654
658
  _createRequestProcessor<T>({
659
+ bundleType,
655
660
  createStartEntry,
656
661
  createEndEntry,
657
662
  build,
658
663
  delete: deleteFn,
659
664
  finish,
660
665
  }: {
666
+ +bundleType: 'assets' | 'bundle' | 'map',
661
667
  +createStartEntry: (context: ProcessStartContext) => ActionLogEntryData,
662
668
  +createEndEntry: (
663
669
  context: ProcessEndContext<T>,
@@ -796,7 +802,7 @@ class Server {
796
802
  this._reporter.update({
797
803
  buildID: getBuildID(buildNumber),
798
804
  bundleDetails: {
799
- bundleType: bundleOptions.bundleType,
805
+ bundleType,
800
806
  customResolverOptions: bundleOptions.customResolverOptions,
801
807
  customTransformOptions: bundleOptions.customTransformOptions,
802
808
  dev: transformOptions.dev,
@@ -895,6 +901,7 @@ class Server {
895
901
  bundlePerfLogger: RootPerfLogger,
896
902
  }>,
897
903
  ) => Promise<void> = this._createRequestProcessor({
904
+ bundleType: 'bundle',
898
905
  createStartEntry(context: ProcessStartContext) {
899
906
  return {
900
907
  action_name: 'Requesting bundle',
@@ -1104,6 +1111,7 @@ class Server {
1104
1111
  bundlePerfLogger: RootPerfLogger,
1105
1112
  }>,
1106
1113
  ) => Promise<void> = this._createRequestProcessor({
1114
+ bundleType: 'map',
1107
1115
  createStartEntry(context: ProcessStartContext) {
1108
1116
  return {
1109
1117
  action_name: 'Requesting sourcemap',
@@ -1175,6 +1183,7 @@ class Server {
1175
1183
  bundlePerfLogger: RootPerfLogger,
1176
1184
  }>,
1177
1185
  ) => Promise<void> = this._createRequestProcessor({
1186
+ bundleType: 'assets',
1178
1187
  createStartEntry(context: ProcessStartContext) {
1179
1188
  return {
1180
1189
  action_name: 'Requesting assets',
package/src/index.flow.js CHANGED
@@ -21,6 +21,7 @@ const {
21
21
  } = require("metro-config");
22
22
  const { Terminal } = require("metro-core");
23
23
  const net = require("net");
24
+ const nullthrows = require("nullthrows");
24
25
  const { parse } = require("url");
25
26
  exports.Terminal = Terminal;
26
27
  exports.TerminalReporter = TerminalReporter;
@@ -216,6 +217,7 @@ exports.runServer = async (
216
217
  exports.runBuild = async (
217
218
  config,
218
219
  {
220
+ assets = false,
219
221
  customResolverOptions,
220
222
  customTransformOptions,
221
223
  dev = false,
@@ -226,9 +228,12 @@ exports.runBuild = async (
226
228
  minify = true,
227
229
  output = outputBundle,
228
230
  out,
231
+ bundleOut,
232
+ sourceMapOut,
229
233
  platform = "web",
230
234
  sourceMap = false,
231
235
  sourceMapUrl,
236
+ unstable_transformProfile,
232
237
  }
233
238
  ) => {
234
239
  const metroServer = await runMetro(config, {
@@ -246,18 +251,31 @@ exports.runBuild = async (
246
251
  onProgress,
247
252
  customResolverOptions,
248
253
  customTransformOptions,
254
+ unstable_transformProfile,
249
255
  };
250
256
  if (onBegin) {
251
257
  onBegin();
252
258
  }
253
259
  const metroBundle = await output.build(metroServer, requestOptions);
260
+ const result = {
261
+ ...metroBundle,
262
+ };
263
+ if (assets) {
264
+ result.assets = await metroServer.getAssets({
265
+ ...MetroServer.DEFAULT_BUNDLE_OPTIONS,
266
+ ...requestOptions,
267
+ });
268
+ }
254
269
  if (onComplete) {
255
270
  onComplete();
256
271
  }
257
- if (out) {
258
- const bundleOutput = out.replace(/(\.js)?$/, ".js");
272
+ if (out || bundleOut) {
273
+ const bundleOutput =
274
+ bundleOut ?? nullthrows(out).replace(/(\.js)?$/, ".js");
259
275
  const sourcemapOutput =
260
- sourceMap === false ? undefined : out.replace(/(\.js)?$/, ".map");
276
+ sourceMap === false
277
+ ? undefined
278
+ : sourceMapOut ?? out?.replace(/(\.js)?$/, ".map");
261
279
  const outputOptions = {
262
280
  bundleOutput,
263
281
  sourcemapOutput,
@@ -271,7 +289,7 @@ exports.runBuild = async (
271
289
  })
272
290
  );
273
291
  }
274
- return metroBundle;
292
+ return result;
275
293
  } finally {
276
294
  await metroServer.end();
277
295
  }
@@ -11,18 +11,20 @@
11
11
 
12
12
  'use strict';
13
13
 
14
+ import type {AssetData} from './Assets';
14
15
  import type {ReadOnlyGraph} from './DeltaBundler';
15
16
  import type {ServerOptions} from './Server';
16
17
  import type {OutputOptions, RequestOptions} from './shared/types.flow.js';
17
18
  import type {HandleFunction} from 'connect';
18
19
  import type {Server as HttpServer} from 'http';
19
20
  import type {Server as HttpsServer} from 'https';
21
+ import type {TransformProfile} from 'metro-babel-transformer';
20
22
  import type {
21
23
  ConfigT,
22
24
  InputConfigT,
23
25
  MetroConfig,
24
26
  Middleware,
25
- } from 'metro-config/src/configTypes.flow';
27
+ } from 'metro-config';
26
28
  import type {CustomResolverOptions} from 'metro-resolver';
27
29
  import type {CustomTransformOptions} from 'metro-transform-worker';
28
30
  import typeof Yargs from 'yargs';
@@ -48,6 +50,7 @@ const {
48
50
  } = require('metro-config');
49
51
  const {Terminal} = require('metro-core');
50
52
  const net = require('net');
53
+ const nullthrows = require('nullthrows');
51
54
  const {parse} = require('url');
52
55
 
53
56
  type MetroMiddleWare = {
@@ -92,8 +95,11 @@ type BuildGraphOptions = {
92
95
 
93
96
  export type RunBuildOptions = {
94
97
  entry: string,
98
+ assets?: boolean,
95
99
  dev?: boolean,
96
100
  out?: string,
101
+ bundleOut?: string,
102
+ sourceMapOut?: string,
97
103
  onBegin?: () => void,
98
104
  onComplete?: () => void,
99
105
  onProgress?: (transformedFileCount: number, totalFileCount: number) => void,
@@ -123,6 +129,14 @@ export type RunBuildOptions = {
123
129
  sourceMapUrl?: string,
124
130
  customResolverOptions?: CustomResolverOptions,
125
131
  customTransformOptions?: CustomTransformOptions,
132
+ unstable_transformProfile?: TransformProfile,
133
+ };
134
+
135
+ export type RunBuildResult = {
136
+ code: string,
137
+ map: string,
138
+ assets?: $ReadOnlyArray<AssetData>,
139
+ ...
126
140
  };
127
141
 
128
142
  type BuildCommandOptions = {} | null;
@@ -131,6 +145,9 @@ type ServeCommandOptions = {} | null;
131
145
  exports.Terminal = Terminal;
132
146
  exports.TerminalReporter = TerminalReporter;
133
147
 
148
+ export type {AssetData} from './Assets';
149
+ export type {Reporter, ReportableEvent} from './lib/reporting';
150
+ export type {TerminalReportableEvent} from './lib/TerminalReporter';
134
151
  export type {MetroConfig};
135
152
 
136
153
  async function getConfig(config: InputConfigT): Promise<ConfigT> {
@@ -369,6 +386,7 @@ exports.runServer = async (
369
386
  exports.runBuild = async (
370
387
  config: ConfigT,
371
388
  {
389
+ assets = false,
372
390
  customResolverOptions,
373
391
  customTransformOptions,
374
392
  dev = false,
@@ -379,15 +397,14 @@ exports.runBuild = async (
379
397
  minify = true,
380
398
  output = outputBundle,
381
399
  out,
400
+ bundleOut,
401
+ sourceMapOut,
382
402
  platform = 'web',
383
403
  sourceMap = false,
384
404
  sourceMapUrl,
405
+ unstable_transformProfile,
385
406
  }: RunBuildOptions,
386
- ): Promise<{
387
- code: string,
388
- map: string,
389
- ...
390
- }> => {
407
+ ): Promise<RunBuildResult> => {
391
408
  const metroServer = await runMetro(config, {
392
409
  watch: false,
393
410
  });
@@ -404,6 +421,7 @@ exports.runBuild = async (
404
421
  onProgress,
405
422
  customResolverOptions,
406
423
  customTransformOptions,
424
+ unstable_transformProfile,
407
425
  };
408
426
 
409
427
  if (onBegin) {
@@ -411,15 +429,27 @@ exports.runBuild = async (
411
429
  }
412
430
 
413
431
  const metroBundle = await output.build(metroServer, requestOptions);
432
+ const result: RunBuildResult = {...metroBundle};
433
+
434
+ if (assets) {
435
+ result.assets = await metroServer.getAssets({
436
+ ...MetroServer.DEFAULT_BUNDLE_OPTIONS,
437
+ ...requestOptions,
438
+ });
439
+ }
414
440
 
415
441
  if (onComplete) {
416
442
  onComplete();
417
443
  }
418
444
 
419
- if (out) {
420
- const bundleOutput = out.replace(/(\.js)?$/, '.js');
445
+ if (out || bundleOut) {
446
+ const bundleOutput =
447
+ bundleOut ?? nullthrows(out).replace(/(\.js)?$/, '.js');
448
+
421
449
  const sourcemapOutput =
422
- sourceMap === false ? undefined : out.replace(/(\.js)?$/, '.map');
450
+ sourceMap === false
451
+ ? undefined
452
+ : sourceMapOut ?? out?.replace(/(\.js)?$/, '.map');
423
453
 
424
454
  const outputOptions: OutputOptions = {
425
455
  bundleOutput,
@@ -436,7 +466,7 @@ exports.runBuild = async (
436
466
  );
437
467
  }
438
468
 
439
- return metroBundle;
469
+ return result;
440
470
  } finally {
441
471
  await metroServer.end();
442
472
  }
@@ -46,6 +46,7 @@ class JsonReporter<TEvent: {[string]: any, ...}> {
46
46
  update(event: TEvent): void {
47
47
  if (event.error instanceof Error) {
48
48
  const {message, stack} = event.error;
49
+ // $FlowFixMe[unsafe-object-assign]
49
50
  event = Object.assign(event, {
50
51
  error: serializeError(event.error),
51
52
  // TODO: Preexisting issue - this writes message, stack, etc. as
@@ -384,6 +384,7 @@ class TerminalReporter {
384
384
  0.999, // make sure not to go above 99.9% to not get rounded to 100%,
385
385
  );
386
386
 
387
+ // $FlowFixMe[unsafe-object-assign]
387
388
  Object.assign(currentProgress, {
388
389
  ratio,
389
390
  transformedFileCount,
@@ -44,7 +44,11 @@ const getTransformProfile = (transformProfile: string): TransformProfile =>
44
44
  module.exports = function parseOptionsFromUrl(
45
45
  normalizedRequestUrl: string,
46
46
  platforms: Set<string>,
47
- ): BundleOptions {
47
+ ): {
48
+ ...BundleOptions,
49
+ // Retained for backwards compatibility, unused in Metro, to be removed.
50
+ bundleType: string,
51
+ } {
48
52
  const parsedURL = nullthrows(url.parse(normalizedRequestUrl, true)); // `true` to parse the query param as an object.
49
53
  const query = nullthrows(parsedURL.query);
50
54
  const pathname =
@@ -21,7 +21,7 @@ import type {
21
21
  import type {TransformOptions} from '../DeltaBundler/Worker';
22
22
  import type {ResolverInputOptions} from '../shared/types.flow';
23
23
  import type {RequireContext} from './contextModule';
24
- import type {ConfigT} from 'metro-config/src/configTypes.flow';
24
+ import type {ConfigT} from 'metro-config';
25
25
  import type {Type} from 'metro-transform-worker';
26
26
 
27
27
  import {getContextModuleTemplate} from './contextModuleTemplates';
@@ -9,7 +9,7 @@
9
9
  * @oncall react_native
10
10
  */
11
11
 
12
- import type {ConfigT} from 'metro-config/src/configTypes.flow';
12
+ import type {ConfigT} from 'metro-config';
13
13
 
14
14
  import MetroFileMap, {DiskCacheManager} from 'metro-file-map';
15
15
 
@@ -15,7 +15,7 @@ import type {
15
15
  } from '../DeltaBundler/types.flow';
16
16
  import type {ResolverInputOptions} from '../shared/types.flow';
17
17
  import type Package from './Package';
18
- import type {ConfigT} from 'metro-config/src/configTypes.flow';
18
+ import type {ConfigT} from 'metro-config';
19
19
  import type MetroFileMap, {
20
20
  ChangeEvent,
21
21
  FileSystem,
@@ -171,12 +171,12 @@ class DependencyGraph extends EventEmitter {
171
171
  const result = this._fileSystem.lookup(path);
172
172
  if (result.exists) {
173
173
  return {
174
- exists: true,
174
+ exists: true as const,
175
175
  realPath: result.realPath,
176
176
  type: result.type,
177
177
  };
178
178
  }
179
- return {exists: false};
179
+ return {exists: false as const};
180
180
  };
181
181
 
182
182
  this._moduleResolver = new ModuleResolver({
@@ -7,7 +7,6 @@ async function build(packagerClient, requestOptions) {
7
7
  const options = {
8
8
  ...Server.DEFAULT_BUNDLE_OPTIONS,
9
9
  ...requestOptions,
10
- bundleType: "ram",
11
10
  };
12
11
  return await packagerClient.getRamBundleInfo(options);
13
12
  }
@@ -25,7 +25,6 @@ async function build(
25
25
  const options = {
26
26
  ...Server.DEFAULT_BUNDLE_OPTIONS,
27
27
  ...requestOptions,
28
- bundleType: 'ram',
29
28
  };
30
29
  return await packagerClient.getRamBundleInfo(options);
31
30
  }
@@ -7,7 +7,6 @@ function buildBundle(packagerClient, requestOptions) {
7
7
  return packagerClient.build({
8
8
  ...Server.DEFAULT_BUNDLE_OPTIONS,
9
9
  ...requestOptions,
10
- bundleType: "bundle",
11
10
  });
12
11
  }
13
12
  function relativateSerializedMap(map, sourceMapSourcesRoot) {
@@ -29,7 +29,6 @@ function buildBundle(
29
29
  return packagerClient.build({
30
30
  ...Server.DEFAULT_BUNDLE_OPTIONS,
31
31
  ...requestOptions,
32
- bundleType: 'bundle',
33
32
  });
34
33
  }
35
34
 
@@ -23,21 +23,9 @@ import type {
23
23
  MinifierOptions,
24
24
  } from 'metro-transform-worker';
25
25
 
26
- export type BundleType =
27
- | 'bundle'
28
- | 'delta'
29
- | 'meta'
30
- | 'map'
31
- | 'ram'
32
- | 'cli'
33
- | 'hmr'
34
- | 'todo'
35
- | 'graph';
36
-
37
26
  type MetroSourceMapOrMappings = MixedSourceMap | MetroSourceMapSegmentTuple[];
38
27
 
39
28
  export interface BundleOptions {
40
- bundleType: BundleType;
41
29
  readonly customResolverOptions: CustomResolverOptions;
42
30
  customTransformOptions: CustomTransformOptions;
43
31
  dev: boolean;
@@ -26,17 +26,6 @@ import type {
26
26
  MinifierOptions,
27
27
  } from 'metro-transform-worker';
28
28
 
29
- type BundleType =
30
- | 'bundle'
31
- | 'delta'
32
- | 'meta'
33
- | 'map'
34
- | 'ram'
35
- | 'cli'
36
- | 'hmr'
37
- | 'todo'
38
- | 'graph';
39
-
40
29
  type MetroSourceMapOrMappings =
41
30
  | MixedSourceMap
42
31
  | Array<MetroSourceMapSegmentTuple>;
@@ -49,7 +38,6 @@ export enum SourcePathsMode {
49
38
  }
50
39
 
51
40
  export type BundleOptions = {
52
- bundleType: BundleType,
53
41
  +customResolverOptions: CustomResolverOptions,
54
42
  customTransformOptions: CustomTransformOptions,
55
43
  dev: boolean,
@@ -151,6 +139,7 @@ export type RequestOptions = {
151
139
  onProgress?: (transformedFileCount: number, totalFileCount: number) => void,
152
140
  +customResolverOptions?: CustomResolverOptions,
153
141
  +customTransformOptions?: CustomTransformOptions,
142
+ +unstable_transformProfile?: TransformProfile,
154
143
  };
155
144
 
156
145
  export type {MinifierOptions};