Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict
*/

export type PackagerAsset = {
+httpServerLocation: string,
+name: string,
+type: string,
};
export interface PackagerAsset {
httpServerLocation: string;
name: string;
type: string;
}

/**
* FIXME: using number to represent discrete scale numbers is fragile in essence because of
Expand All @@ -38,7 +36,7 @@ function getAndroidAssetSuffix(scale: number): string {
}

// See https://developer.android.com/guide/topics/resources/drawable-resource.html
const drawableFileTypes = new Set([
const drawableFileTypes = new Set<string>([
'gif',
'jpeg',
'jpg',
Expand All @@ -48,7 +46,10 @@ const drawableFileTypes = new Set([
'xml',
]);

function getAndroidResourceFolderName(asset: PackagerAsset, scale: number) {
function getAndroidResourceFolderName(
asset: PackagerAsset,
scale: number,
): string {
if (!drawableFileTypes.has(asset.type)) {
return 'raw';
}
Expand All @@ -64,7 +65,7 @@ function getAndroidResourceFolderName(asset: PackagerAsset, scale: number) {
return androidFolder;
}

function getAndroidResourceIdentifier(asset: PackagerAsset) {
function getAndroidResourceIdentifier(asset: PackagerAsset): string {
const folderPath = getBasePath(asset);
return `${folderPath}/${asset.name}`
.toLowerCase()
Expand All @@ -73,7 +74,7 @@ function getAndroidResourceIdentifier(asset: PackagerAsset) {
.replace(/^assets_/, ''); // Remove "assets_" prefix
}

function getBasePath(asset: PackagerAsset) {
function getBasePath(asset: PackagerAsset): string {
let basePath = asset.httpServerLocation;
if (basePath[0] === '/') {
basePath = basePath.substr(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,44 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

// @ts-ignore - no typed definition for the package
import Server from 'metro/src/Server';

// @ts-ignore - no typed definition for the package
import outputBundle from 'metro/src/shared/output/bundle';
import path from 'path';
import chalk from 'chalk';
import type {CommandLineArgs} from './bundleCommandLineArgs';
import type {ConfigT} from 'types';
import {CommandLineArgs} from './bundleCommandLineArgs';
import {Config} from '@react-native-community/cli-types';
import saveAssets from './saveAssets';
// $FlowFixMe - converted to typescript
import loadMetroConfig from '../../tools/loadMetroConfig';
import {logger} from '@react-native-community/cli-tools';

interface RequestOptions {
entryFile: string;
sourceMapUrl: string | undefined;
dev: boolean;
minify: boolean;
platform: string | undefined;
}

export interface AssetData {
__packager_asset: boolean;
fileSystemLocation: string;
hash: string;
height: number | null;
httpServerLocation: string;
name: string;
scales: number[];
type: string;
width: number | null;
files: string[];
}

async function buildBundle(
args: CommandLineArgs,
ctx: ConfigT,
ctx: Config,
output: typeof outputBundle = outputBundle,
) {
const config = await loadMetroConfig(ctx, {
Expand Down Expand Up @@ -73,7 +93,7 @@ async function buildBundle(
await output.save(bundle, args, logger.info);

// Save the assets of the bundle
const outputAssets = await server.getAssets({
const outputAssets: AssetData[] = await server.getAssets({
...Server.DEFAULT_BUNDLE_OPTIONS,
...requestOpts,
bundleType: 'todo',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/

import {Config} from '@react-native-community/cli-types';
import buildBundle from './buildBundle';
import bundleCommandLineArgs from './bundleCommandLineArgs';
import bundleCommandLineArgs, {CommandLineArgs} from './bundleCommandLineArgs';

/**
* Builds the bundle starting to look for dependencies at the given entry path.
*/
function bundleWithOutput(_, config, args, output) {
function bundleWithOutput(
_: Array<string>,
config: Config,
args: CommandLineArgs,
output: any, // untyped metro/src/shared/output/bundle or metro/src/shared/output/RamBundle
) {
return buildBundle(args, config, output);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,28 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import path from 'path';

export type CommandLineArgs = {
assetsDest?: string,
entryFile: string,
resetCache: boolean,
resetGlobalCache: boolean,
transformer?: string,
minify?: boolean,
config?: string,
platform?: string,
dev: boolean,
bundleOutput: string,
bundleEncoding?: string,
maxWorkers?: number,
sourcemapOutput?: string,
sourcemapSourcesRoot?: string,
sourcemapUseAbsolutePath: boolean,
verbose: boolean,
};
export interface CommandLineArgs {
assetsDest?: string;
entryFile: string;
resetCache: boolean;
resetGlobalCache: boolean;
transformer?: string;
minify?: boolean;
config?: string;
platform: string;
dev: boolean;
bundleOutput: string;
bundleEncoding?: string;
maxWorkers?: number;
sourcemapOutput?: string;
sourcemapSourcesRoot?: string;
sourcemapUseAbsolutePath: boolean;
verbose: boolean;
}

export default [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/

const ALLOWED_SCALES = {
const ALLOWED_SCALES: {[key: string]: number[]} = {
ios: [1, 2, 3],
};

function filterPlatformAssetScales(
platform: string,
scales: $ReadOnlyArray<number>,
): $ReadOnlyArray<number> {
const whitelist = ALLOWED_SCALES[platform];
scales: ReadonlyArray<number>,
): ReadonlyArray<number> {
const whitelist: number[] = ALLOWED_SCALES[platform];
if (!whitelist) {
return scales;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict
*/

import path from 'path';
import type {PackagerAsset} from './assetPathUtils';

import assetPathUtils from './assetPathUtils';
import assetPathUtils, {PackagerAsset} from './assetPathUtils';

function getAssetDestPathAndroid(asset: PackagerAsset, scale: number): string {
const androidFolder = assetPathUtils.getAndroidResourceFolderName(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict
*/

import path from 'path';
import type {PackagerAsset} from './assetPathUtils';
import {PackagerAsset} from './assetPathUtils';

function getAssetDestPathIOS(asset: PackagerAsset, scale: number): string {
const suffix = scale === 1 ? '' : `@${scale}x`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
// @ts-ignore - no typed definition for the package
import outputUnbundle from 'metro/src/shared/output/RamBundle';

import {withOutput as bundleWithOutput} from './bundle';
import bundleCommandLineArgs from './bundleCommandLineArgs';
import bundleCommandLineArgs, {CommandLineArgs} from './bundleCommandLineArgs';
import {Config} from '@react-native-community/cli-types';

/**
* Builds the bundle starting to look for dependencies at the given entry path.
*/
function ramBundle(argv, config, args) {
function ramBundle(argv: Array<string>, config: Config, args: CommandLineArgs) {
return bundleWithOutput(argv, config, args, outputUnbundle);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/

import mkdirp from 'mkdirp';
Expand All @@ -15,8 +14,17 @@ import filterPlatformAssetScales from './filterPlatformAssetScales';
import getAssetDestPathAndroid from './getAssetDestPathAndroid';
import getAssetDestPathIOS from './getAssetDestPathIOS';
import {logger} from '@react-native-community/cli-tools';
import {AssetData} from './buildBundle';

function saveAssets(assets, platform, assetsDest) {
interface CopiedFiles {
[src: string]: string;
}

function saveAssets(
assets: AssetData[],
platform: string,
assetsDest: string | undefined,
) {
if (!assetsDest) {
logger.warn('Assets destination folder is not set, skipping...');
return Promise.resolve();
Expand All @@ -25,7 +33,7 @@ function saveAssets(assets, platform, assetsDest) {
const getAssetDestPath =
platform === 'android' ? getAssetDestPathAndroid : getAssetDestPathIOS;

const filesToCopy = Object.create(null); // Map src -> dest
const filesToCopy: CopiedFiles = Object.create(null); // Map src -> dest
assets.forEach(asset => {
const validScales = new Set(
filterPlatformAssetScales(platform, asset.scales),
Expand All @@ -43,15 +51,15 @@ function saveAssets(assets, platform, assetsDest) {
return copyAll(filesToCopy);
}

function copyAll(filesToCopy) {
function copyAll(filesToCopy: CopiedFiles) {
const queue = Object.keys(filesToCopy);
if (queue.length === 0) {
return Promise.resolve();
}

logger.info(`Copying ${queue.length} asset files`);
return new Promise((resolve, reject) => {
const copyNext = error => {
const copyNext = (error?: NodeJS.ErrnoException) => {
if (error) {
reject(error);
return;
Expand All @@ -60,7 +68,8 @@ function copyAll(filesToCopy) {
logger.info('Done copying assets');
resolve();
} else {
const src = queue.shift();
// queue.length === 0 is checked in previous branch, so this is string
const src = queue.shift() as string;
const dest = filesToCopy[src];
copy(src, dest, copyNext);
}
Expand All @@ -69,9 +78,13 @@ function copyAll(filesToCopy) {
});
}

function copy(src, dest, callback) {
function copy(
src: string,
dest: string,
callback: (error: NodeJS.ErrnoException) => void,
): void {
const destDir = path.dirname(dest);
mkdirp(destDir, err => {
mkdirp(destDir, (err?: NodeJS.ErrnoException) => {
if (err) {
callback(err);
return;
Expand Down
9 changes: 6 additions & 3 deletions packages/cli/src/tools/loadMetroConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const INTERNAL_CALLSITES_REGEX = new RegExp(
].join('|'),
);

export interface DefaultConfigOption {
export interface MetroConfig {
resolver: {
resolverMainFields: string[];
blacklistRE: RegExp;
Expand Down Expand Up @@ -64,7 +64,7 @@ export interface DefaultConfigOption {
* @todo(grabbou): As a separate PR, haste.platforms should be added before "native".
* Otherwise, a.native.js will not load on Windows or other platforms
*/
export const getDefaultConfig = (ctx: Config): DefaultConfigOption => {
export const getDefaultConfig = (ctx: Config): MetroConfig => {
const hasteImplPath = path.join(ctx.reactNativePath, 'jest/hasteImpl.js');
return {
resolver: {
Expand Down Expand Up @@ -125,7 +125,10 @@ export interface ConfigOptionsT {
*
* This allows the CLI to always overwrite the file settings.
*/
export default function load(ctx: Config, options?: ConfigOptionsT) {
export default function load(
ctx: Config,
options?: ConfigOptionsT,
): Promise<MetroConfig> {
const defaultConfig = getDefaultConfig(ctx);
if (options && options.reporter) {
/**
Expand Down