1fd2402c1SEvan Baconimport fs from 'fs'; 2fd2402c1SEvan Baconimport Server from 'metro/src/Server'; 3fd2402c1SEvan Baconimport output from 'metro/src/shared/output/bundle'; 4fd2402c1SEvan Baconimport type { BundleOptions } from 'metro/src/shared/types'; 5fd2402c1SEvan Baconimport path from 'path'; 6fd2402c1SEvan Bacon 78a424bebSJames Ideimport { Options } from './resolveOptions'; 8fd2402c1SEvan Baconimport { Log } from '../../log'; 9b6b91c50SEvan Baconimport { loadMetroConfigAsync } from '../../start/server/metro/instantiateMetro'; 10fd2402c1SEvan Baconimport { importCliSaveAssetsFromProject } from '../../start/server/metro/resolveFromProject'; 11000843d8SEvan Baconimport { setNodeEnv } from '../../utils/nodeEnv'; 12fd2402c1SEvan Baconimport { getAssets } from '../fork-bundleAsync'; 13b6b91c50SEvan Bacon 14b6b91c50SEvan Baconexport async function exportEmbedAsync(projectRoot: string, options: Options) { 15000843d8SEvan Bacon setNodeEnv(options.dev ? 'development' : 'production'); 166a750d06SEvan Bacon require('@expo/env').load(projectRoot); 17000843d8SEvan Bacon 18429dc7fcSEvan Bacon const { config } = await loadMetroConfigAsync( 19429dc7fcSEvan Bacon projectRoot, 20429dc7fcSEvan Bacon { 21b6b91c50SEvan Bacon maxWorkers: options.maxWorkers, 22b6b91c50SEvan Bacon resetCache: options.resetCache, 23b6b91c50SEvan Bacon config: options.config, 24429dc7fcSEvan Bacon }, 25429dc7fcSEvan Bacon { 26429dc7fcSEvan Bacon isExporting: true, 27429dc7fcSEvan Bacon } 28429dc7fcSEvan Bacon ); 29b6b91c50SEvan Bacon 30*7c98c357SEvan Bacon // NOTE(EvanBacon): This may need to be adjusted in the future if want to support basePath on native 31*7c98c357SEvan Bacon // platforms when doing production embeds (unlikely). 32fd2402c1SEvan Bacon const saveAssets = importCliSaveAssetsFromProject(projectRoot); 33b6b91c50SEvan Bacon 34fd2402c1SEvan Bacon let sourceMapUrl = options.sourcemapOutput; 35fd2402c1SEvan Bacon if (sourceMapUrl && !options.sourcemapUseAbsolutePath) { 36fd2402c1SEvan Bacon sourceMapUrl = path.basename(sourceMapUrl); 37fd2402c1SEvan Bacon } 38fd2402c1SEvan Bacon 39fd2402c1SEvan Bacon const bundleRequest = { 40fd2402c1SEvan Bacon ...Server.DEFAULT_BUNDLE_OPTIONS, 41fd2402c1SEvan Bacon entryFile: options.entryFile, 42fd2402c1SEvan Bacon sourceMapUrl, 43fd2402c1SEvan Bacon dev: options.dev, 44fd2402c1SEvan Bacon minify: !!options.minify, 45fd2402c1SEvan Bacon platform: options.platform, 46fd2402c1SEvan Bacon unstable_transformProfile: 47fd2402c1SEvan Bacon options.unstableTransformProfile as BundleOptions['unstable_transformProfile'], 48fd2402c1SEvan Bacon }; 49fd2402c1SEvan Bacon 50fd2402c1SEvan Bacon const server = new Server(config, { 51fd2402c1SEvan Bacon watch: false, 52fd2402c1SEvan Bacon }); 53fd2402c1SEvan Bacon 54fd2402c1SEvan Bacon try { 55fd2402c1SEvan Bacon const bundle = await server.build({ 56fd2402c1SEvan Bacon ...bundleRequest, 57fd2402c1SEvan Bacon bundleType: 'bundle', 58fd2402c1SEvan Bacon }); 59fd2402c1SEvan Bacon 60fd2402c1SEvan Bacon fs.mkdirSync(path.dirname(options.bundleOutput), { recursive: true, mode: 0o755 }); 61fd2402c1SEvan Bacon 62fd2402c1SEvan Bacon // Persist bundle and source maps. 63fd2402c1SEvan Bacon await output.save(bundle, options, Log.log); 64fd2402c1SEvan Bacon 65fd2402c1SEvan Bacon // Save the assets of the bundle 66fd2402c1SEvan Bacon const outputAssets = await getAssets(server, { 67fd2402c1SEvan Bacon ...bundleRequest, 68fd2402c1SEvan Bacon bundleType: 'todo', 69fd2402c1SEvan Bacon }); 70fd2402c1SEvan Bacon 71fd2402c1SEvan Bacon await saveAssets(outputAssets, options.platform, options.assetsDest, options.assetCatalogDest); 72fd2402c1SEvan Bacon } finally { 73fd2402c1SEvan Bacon server.end(); 74fd2402c1SEvan Bacon } 75b6b91c50SEvan Bacon} 76