1import fs from 'fs';
2import Server from 'metro/src/Server';
3import output from 'metro/src/shared/output/bundle';
4import type { BundleOptions } from 'metro/src/shared/types';
5import path from 'path';
6
7import { Options } from './resolveOptions';
8import { Log } from '../../log';
9import { loadMetroConfigAsync } from '../../start/server/metro/instantiateMetro';
10import { importCliSaveAssetsFromProject } from '../../start/server/metro/resolveFromProject';
11import { setNodeEnv } from '../../utils/nodeEnv';
12import { getAssets } from '../fork-bundleAsync';
13
14export async function exportEmbedAsync(projectRoot: string, options: Options) {
15  setNodeEnv(options.dev ? 'development' : 'production');
16  require('@expo/env').load(projectRoot);
17
18  const { config } = await loadMetroConfigAsync(projectRoot, {
19    maxWorkers: options.maxWorkers,
20    resetCache: options.resetCache,
21    config: options.config,
22  });
23
24  const saveAssets = importCliSaveAssetsFromProject(projectRoot);
25
26  let sourceMapUrl = options.sourcemapOutput;
27  if (sourceMapUrl && !options.sourcemapUseAbsolutePath) {
28    sourceMapUrl = path.basename(sourceMapUrl);
29  }
30
31  const bundleRequest = {
32    ...Server.DEFAULT_BUNDLE_OPTIONS,
33    entryFile: options.entryFile,
34    sourceMapUrl,
35    dev: options.dev,
36    minify: !!options.minify,
37    platform: options.platform,
38    unstable_transformProfile:
39      options.unstableTransformProfile as BundleOptions['unstable_transformProfile'],
40  };
41
42  const server = new Server(config, {
43    watch: false,
44  });
45
46  try {
47    const bundle = await server.build({
48      ...bundleRequest,
49      bundleType: 'bundle',
50    });
51
52    fs.mkdirSync(path.dirname(options.bundleOutput), { recursive: true, mode: 0o755 });
53
54    // Persist bundle and source maps.
55    await output.save(bundle, options, Log.log);
56
57    // Save the assets of the bundle
58    const outputAssets = await getAssets(server, {
59      ...bundleRequest,
60      bundleType: 'todo',
61    });
62
63    await saveAssets(outputAssets, options.platform, options.assetsDest, options.assetCatalogDest);
64  } finally {
65    server.end();
66  }
67}
68