#!/usr/bin/env node import arg from 'arg'; import chalk from 'chalk'; import path from 'path'; import { getMissingAssetsAsync } from './assetsVerifyAsync'; import { isValidPlatform, validPlatforms, type ValidatedOptions, type Platform, } from './assetsVerifyTypes'; import { Command } from './cli'; import { assertArgs, getProjectRoot } from './utils/args'; import { CommandError } from './utils/errors'; import * as Log from './utils/log'; const debug = require('debug')('expo-updates:assets:verify') as typeof console.log; export const expoAssetsVerify: Command = async (argv) => { const args = assertArgs( { // Types '--asset-map-path': String, '--exported-manifest-path': String, '--build-manifest-path': String, '--platform': String, '--help': Boolean, // Aliases '-a': '--asset-map-path', '-e': '--exported-manifest-path', '-b': '--build-manifest-path', '-p': '--platform', '-h': '--help', }, argv ?? [] ); if (args['--help']) { Log.exit( chalk` {bold Description} Verify that all static files in an exported bundle are in either the export or an embedded bundle {bold Usage} {dim $} npx expo-updates assets:verify {dim } Options Directory of the Expo project. Default: Current working directory -a, --asset-map-path Path to the \`assetmap.json\` in an export produced by the command \`npx expo export --dump-assetmap\` -e, --exported-manifest-path Path to the \`metadata.json\` in an export produced by the command \`npx expo export --dump-assetmap\` -b, --build-manifest-path Path to the \`app.manifest\` file created by expo-updates in an Expo application build (either ios or android) -p, --platform Options: ${JSON.stringify(validPlatforms)} -h, --help Usage info `, 0 ); } const projectRoot = getProjectRoot(args); const validatedArgs = resolveOptions(projectRoot, args); debug(`Validated params: ${JSON.stringify(validatedArgs, null, 2)}`); const { buildManifestPath, exportedManifestPath, assetMapPath, platform } = validatedArgs; const missingAssets = await getMissingAssetsAsync( buildManifestPath, exportedManifestPath, assetMapPath, platform ); if (missingAssets.length > 0) { throw new CommandError( `${ missingAssets.length } assets not found in either embedded manifest or in exported bundle:${JSON.stringify( missingAssets, null, 2 )}` ); } else { Log.log(`All resolved assets found in either embedded manifest or in exported bundle.`); } }; function resolveOptions(projectRoot: string, args: arg.Result): ValidatedOptions { const exportedManifestPath = validatedPathFromArgument( projectRoot, args, '--exported-manifest-path' ); const buildManifestPath = validatedPathFromArgument(projectRoot, args, '--build-manifest-path'); const assetMapPath = validatedPathFromArgument(projectRoot, args, '--asset-map-path'); const platform = args['--platform'] as unknown as Platform; if (!isValidPlatform(platform)) { throw new CommandError(`Platform must be one of ${JSON.stringify(validPlatforms)}`); } return { exportedManifestPath, buildManifestPath, assetMapPath, platform, }; } function validatedPathFromArgument(projectRoot: string, args: arg.Result, key: string) { const maybeRelativePath = args[key] as unknown as string; if (!maybeRelativePath) { throw new CommandError(`No value for ${key}`); } if (maybeRelativePath.indexOf('/') === 0) { return maybeRelativePath; // absolute path } return path.resolve(projectRoot, maybeRelativePath); }