diff --git a/packages/cli-plugin-metro/package.json b/packages/cli-plugin-metro/package.json index d39dac087..2e7ddcf82 100644 --- a/packages/cli-plugin-metro/package.json +++ b/packages/cli-plugin-metro/package.json @@ -20,7 +20,11 @@ "readline": "^1.3.0" }, "devDependencies": { - "@react-native-community/cli-types": "^11.0.0-alpha.2" + "@react-native-community/cli-types": "^11.0.0-alpha.2", + "@types/metro": "^0.76.0", + "@types/metro-config": "^0.76.1", + "@types/metro-core": "^0.76.0", + "@types/metro-resolver": "^0.76.1" }, "files": [ "build", diff --git a/packages/cli-plugin-metro/src/commands/bundle/assetCatalogIOS.ts b/packages/cli-plugin-metro/src/commands/bundle/assetCatalogIOS.ts index a90be8faa..92cf8d9da 100644 --- a/packages/cli-plugin-metro/src/commands/bundle/assetCatalogIOS.ts +++ b/packages/cli-plugin-metro/src/commands/bundle/assetCatalogIOS.ts @@ -8,8 +8,8 @@ import path from 'path'; import fs from 'fs-extra'; +import type {AssetData} from 'metro'; import assetPathUtils from './assetPathUtils'; -import {AssetData} from './buildBundle'; export function cleanAssetCatalog(catalogDir: string): void { const files = fs diff --git a/packages/cli-plugin-metro/src/commands/bundle/buildBundle.ts b/packages/cli-plugin-metro/src/commands/bundle/buildBundle.ts index ca424e45a..5d3feb8b8 100644 --- a/packages/cli-plugin-metro/src/commands/bundle/buildBundle.ts +++ b/packages/cli-plugin-metro/src/commands/bundle/buildBundle.ts @@ -6,19 +6,17 @@ * */ -// @ts-ignore - no typed definition for the package import Server from 'metro/src/Server'; // @ts-ignore - no typed definition for the package const outputBundle = require('metro/src/shared/output/bundle'); +import type {BundleOptions} from 'metro/shared/types'; +import type {ConfigT} from 'metro-config'; import path from 'path'; import chalk from 'chalk'; import {CommandLineArgs} from './bundleCommandLineArgs'; import type {Config} from '@react-native-community/cli-types'; import saveAssets from './saveAssets'; -import { - default as loadMetroConfig, - MetroConfig, -} from '../../tools/loadMetroConfig'; +import {default as loadMetroConfig} from '../../tools/loadMetroConfig'; import {logger} from '@react-native-community/cli-tools'; interface RequestOptions { @@ -27,23 +25,10 @@ interface RequestOptions { dev: boolean; minify: boolean; platform: string | undefined; - unstable_transformProfile: string | undefined; + unstable_transformProfile: BundleOptions['unstable_transformProfile']; generateStaticViewConfigs: boolean; } -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: Config, @@ -65,7 +50,7 @@ async function buildBundle( */ export async function buildBundleWithConfig( args: CommandLineArgs, - config: MetroConfig, + config: ConfigT, output: typeof outputBundle = outputBundle, ) { if (config.resolver.platforms.indexOf(args.platform) === -1) { @@ -101,7 +86,7 @@ export async function buildBundleWithConfig( dev: args.dev, minify: args.minify !== undefined ? args.minify : !args.dev, platform: args.platform, - unstable_transformProfile: args.unstableTransformProfile, + unstable_transformProfile: args.unstableTransformProfile as BundleOptions['unstable_transformProfile'], generateStaticViewConfigs: args.generateStaticViewConfigs, }; const server = new Server(config); @@ -112,7 +97,7 @@ export async function buildBundleWithConfig( await output.save(bundle, args, logger.info); // Save the assets of the bundle - const outputAssets: AssetData[] = await server.getAssets({ + const outputAssets = await server.getAssets({ ...Server.DEFAULT_BUNDLE_OPTIONS, ...requestOpts, bundleType: 'todo', diff --git a/packages/cli-plugin-metro/src/commands/bundle/bundleCommandLineArgs.ts b/packages/cli-plugin-metro/src/commands/bundle/bundleCommandLineArgs.ts index c63a90eb2..a0b9826b5 100644 --- a/packages/cli-plugin-metro/src/commands/bundle/bundleCommandLineArgs.ts +++ b/packages/cli-plugin-metro/src/commands/bundle/bundleCommandLineArgs.ts @@ -26,7 +26,7 @@ export interface CommandLineArgs { sourcemapSourcesRoot?: string; sourcemapUseAbsolutePath: boolean; verbose: boolean; - unstableTransformProfile?: string; + unstableTransformProfile: string; generateStaticViewConfigs: boolean; } @@ -102,6 +102,7 @@ export default [ name: '--unstable-transform-profile ', description: 'Experimental, transform JS for a specific JS engine. Currently supported: hermes, hermes-canary, default', + default: 'default', }, { name: '--asset-catalog-dest [string]', diff --git a/packages/cli-plugin-metro/src/commands/bundle/saveAssets.ts b/packages/cli-plugin-metro/src/commands/bundle/saveAssets.ts index 800e5762d..28ed6330c 100644 --- a/packages/cli-plugin-metro/src/commands/bundle/saveAssets.ts +++ b/packages/cli-plugin-metro/src/commands/bundle/saveAssets.ts @@ -8,6 +8,7 @@ import {logger} from '@react-native-community/cli-tools'; import fs from 'fs'; +import type {AssetData} from 'metro'; import path from 'path'; import { cleanAssetCatalog, @@ -15,7 +16,6 @@ import { isCatalogAsset, writeImageSet, } from './assetCatalogIOS'; -import {AssetData} from './buildBundle'; import filterPlatformAssetScales from './filterPlatformAssetScales'; import getAssetDestPathAndroid from './getAssetDestPathAndroid'; import getAssetDestPathIOS from './getAssetDestPathIOS'; @@ -25,7 +25,7 @@ interface CopiedFiles { } function saveAssets( - assets: AssetData[], + assets: ReadonlyArray, platform: string, assetsDest: string | undefined, assetCatalogDest: string | undefined, diff --git a/packages/cli-plugin-metro/src/commands/start/runServer.ts b/packages/cli-plugin-metro/src/commands/start/runServer.ts index 063778e0c..d7662377e 100644 --- a/packages/cli-plugin-metro/src/commands/start/runServer.ts +++ b/packages/cli-plugin-metro/src/commands/start/runServer.ts @@ -7,7 +7,8 @@ // @ts-ignore untyped metro import Metro from 'metro'; -// @ts-ignore untyped metro +import type {Server} from 'metro'; +import type {Middleware} from 'metro-config'; import {Terminal} from 'metro-core'; import path from 'path'; import { @@ -65,6 +66,7 @@ async function runServer(_argv: Array, ctx: Config, args: Args) { }); if (args.assetPlugins) { + // @ts-ignore - assigning to readonly property metroConfig.transformer.assetPlugins = args.assetPlugins.map((plugin) => require.resolve(plugin), ); @@ -83,9 +85,10 @@ async function runServer(_argv: Array, ctx: Config, args: Args) { middleware.use(indexPageMiddleware); const customEnhanceMiddleware = metroConfig.server.enhanceMiddleware; + // @ts-ignore - assigning to readonly property metroConfig.server.enhanceMiddleware = ( - metroMiddleware: any, - server: unknown, + metroMiddleware: Middleware, + server: Server, ) => { if (customEnhanceMiddleware) { metroMiddleware = customEnhanceMiddleware(metroMiddleware, server); @@ -99,6 +102,7 @@ async function runServer(_argv: Array, ctx: Config, args: Args) { secureCert: args.cert, secureKey: args.key, hmrEnabled: true, + // @ts-ignore - ws.Server types are incompatible websocketEndpoints, }); diff --git a/packages/cli-plugin-metro/src/index.ts b/packages/cli-plugin-metro/src/index.ts index 5951018e1..0367bc8b7 100644 --- a/packages/cli-plugin-metro/src/index.ts +++ b/packages/cli-plugin-metro/src/index.ts @@ -1,7 +1,7 @@ +export type {MetroConfig} from 'metro-config'; export { Config, ConfigLoadingContext, - MetroConfig, getDefaultConfig, default as loadMetroConfig, } from './tools/loadMetroConfig'; diff --git a/packages/cli-plugin-metro/src/tools/__tests__/loadMetroConfig-test.ts b/packages/cli-plugin-metro/src/tools/__tests__/loadMetroConfig-test.ts index 66dd75b0a..eb18d0b53 100644 --- a/packages/cli-plugin-metro/src/tools/__tests__/loadMetroConfig-test.ts +++ b/packages/cli-plugin-metro/src/tools/__tests__/loadMetroConfig-test.ts @@ -12,6 +12,6 @@ describe('getDefaultConfig', () => { platforms: {}, }); - expect(config.transformer.allowOptionalDependencies).toBe(true); + expect(config.transformer?.allowOptionalDependencies).toBe(true); }); }); diff --git a/packages/cli-plugin-metro/src/tools/loadMetroConfig.ts b/packages/cli-plugin-metro/src/tools/loadMetroConfig.ts index 4d0b79c91..01d5f81d8 100644 --- a/packages/cli-plugin-metro/src/tools/loadMetroConfig.ts +++ b/packages/cli-plugin-metro/src/tools/loadMetroConfig.ts @@ -2,8 +2,7 @@ * Configuration file of Metro. */ import path from 'path'; -// @ts-ignore - no typed definition for the package -import {loadConfig} from 'metro-config'; +import {ConfigT, InputConfigT, loadConfig} from 'metro-config'; import type {Config} from '@react-native-community/cli-types'; import {reactNativePlatformResolver} from './metroPlatformResolver'; @@ -34,44 +33,10 @@ export type ConfigLoadingContext = Pick< 'root' | 'reactNativePath' | 'platforms' >; -export interface MetroConfig { - resolver: { - resolveRequest?: ( - context: any, - realModuleName: string, - platform: string, - moduleName: string, - ) => any; - resolverMainFields: string[]; - platforms: string[]; - unstable_conditionNames: string[]; - }; - serializer: { - getModulesRunBeforeMainModule: () => string[]; - getPolyfills: () => any; - }; - server: { - port: number; - enhanceMiddleware?: Function; - }; - symbolicator: { - customizeFrame: (frame: {file: string | null}) => {collapse: boolean}; - }; - transformer: { - allowOptionalDependencies?: boolean; - babelTransformerPath: string; - assetRegistryPath: string; - assetPlugins?: Array; - asyncRequireModulePath?: string; - }; - watchFolders: ReadonlyArray; - reporter?: any; -} - /** * Default configuration */ -export const getDefaultConfig = (ctx: ConfigLoadingContext): MetroConfig => { +export const getDefaultConfig = (ctx: ConfigLoadingContext): InputConfigT => { const outOfTreePlatforms = Object.keys(ctx.platforms).filter( (platform) => ctx.platforms[platform].npmPackageName, ); @@ -115,7 +80,7 @@ export const getDefaultConfig = (ctx: ConfigLoadingContext): MetroConfig => { port: Number(process.env.RCT_METRO_PORT) || 8081, }, symbolicator: { - customizeFrame: (frame: {file: string | null}) => { + customizeFrame: (frame) => { const collapse = Boolean( frame.file && INTERNAL_CALLSITES_REGEX.test(frame.file), ); @@ -155,8 +120,8 @@ export interface ConfigOptionsT { export default function loadMetroConfig( ctx: ConfigLoadingContext, options?: ConfigOptionsT, -): Promise { - const defaultConfig = getDefaultConfig(ctx); +): Promise { + const defaultConfig = {...getDefaultConfig(ctx)}; if (options && options.reporter) { defaultConfig.reporter = options.reporter; } diff --git a/packages/cli-plugin-metro/src/tools/metroPlatformResolver.ts b/packages/cli-plugin-metro/src/tools/metroPlatformResolver.ts index 29dfe58a3..39845f384 100644 --- a/packages/cli-plugin-metro/src/tools/metroPlatformResolver.ts +++ b/packages/cli-plugin-metro/src/tools/metroPlatformResolver.ts @@ -13,12 +13,14 @@ * } */ +import type {CustomResolver} from 'metro-resolver'; + export function reactNativePlatformResolver(platformImplementations: { [platform: string]: string; -}) { - return (context: any, moduleName: string, platform: string) => { +}): CustomResolver { + return (context, moduleName, platform) => { let modifiedModuleName = moduleName; - if (platformImplementations[platform]) { + if (platform != null && platformImplementations[platform]) { if (moduleName === 'react-native') { modifiedModuleName = platformImplementations[platform]; } else if (moduleName.startsWith('react-native/')) { diff --git a/yarn.lock b/yarn.lock index 714b64c15..3bf31a375 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2677,6 +2677,11 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== +"@types/babel__code-frame@*": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@types/babel__code-frame/-/babel__code-frame-7.0.3.tgz#eda94e1b7c9326700a4b69c485ebbc9498a0b63f" + integrity sha512-2TN6oiwtNjOezilFVl77zwdNPwQWaDBBCCWWxyo1ctiO3vAtd7H/aB/CBJdw9+kqq3+latD0SXoedIuHySSZWw== + "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.9" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d" @@ -2890,6 +2895,79 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.149.tgz#1342d63d948c6062838fbf961012f74d4e638440" integrity sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ== +"@types/metro-babel-transformer@*": + version "0.76.0" + resolved "https://registry.yarnpkg.com/@types/metro-babel-transformer/-/metro-babel-transformer-0.76.0.tgz#59ecb66e4168db5fbe712c0636eefdeee4ffde95" + integrity sha512-ctZPAeNrR9HOvH968gCMPa2YAFDkGhqhoceYlXB+Tp/eQu/crzUR3I7j9UKv8t9enuvd5OWLAQm3hJz+QCtPZg== + dependencies: + "@types/metro-source-map" "*" + +"@types/metro-cache@*": + version "0.76.0" + resolved "https://registry.yarnpkg.com/@types/metro-cache/-/metro-cache-0.76.0.tgz#7762fde7172bba2779ec7355fa4f31a511abf2ee" + integrity sha512-5YsoNnEWQ3X2OI1whVItKeL7iMLHIQg3aWKHGsK3Idau6MTTSQMjw/oh2SbTiiHdzrBaXJfQ25ApMPCMMdurDg== + dependencies: + "@types/node" "*" + +"@types/metro-config@*", "@types/metro-config@^0.76.1": + version "0.76.1" + resolved "https://registry.yarnpkg.com/@types/metro-config/-/metro-config-0.76.1.tgz#7deab1b73132f84c04478610ac840bf92e0851e1" + integrity sha512-xA82orx+zGHTl3Tky4pUDfFvWXAm+NtGR71Ux45KzJrX/ooppYPZGy/wez4L78pUcHEt4KQoIefoONvNeb4F3A== + dependencies: + "@types/metro" "*" + "@types/metro-cache" "*" + "@types/metro-resolver" "*" + "@types/metro-transform-worker" "*" + +"@types/metro-core@*", "@types/metro-core@^0.76.0": + version "0.76.0" + resolved "https://registry.yarnpkg.com/@types/metro-core/-/metro-core-0.76.0.tgz#ce9f425abd48431681922ac4f13a3efc9fd1d0e3" + integrity sha512-7iBXd1CiBNHVBPrVbjG2xy8KJq1l6aohQftyqH89FZL/h1cwxxgxt3QtdeYGN7ATOgqAl7iI3BkRd2th4diBvA== + dependencies: + "@types/node" "*" + +"@types/metro-file-map@*": + version "0.76.0" + resolved "https://registry.yarnpkg.com/@types/metro-file-map/-/metro-file-map-0.76.0.tgz#feb5573c57ee5c7d53268c1bf69c00f1c3bfccde" + integrity sha512-61sPxJZG5zEn/8grZfapDOBN517Z4ejHjXrcnMkudBxLrtCxLOcC495JRIfEn7mvV776Z488mNYGMfoPApht2A== + dependencies: + "@types/metro-config" "*" + +"@types/metro-resolver@*", "@types/metro-resolver@^0.76.1": + version "0.76.1" + resolved "https://registry.yarnpkg.com/@types/metro-resolver/-/metro-resolver-0.76.1.tgz#bf0f6f7224fd5b22571abc4b8cbe9f0eed6104d3" + integrity sha512-GAzz8yV7azX1RWmRSLsdPe1ml2vOmaJftirLR/7lSMmDOPJ8G/n8VdnjuoI0uOvth7EmFRwyGBBzF7nceenvOQ== + +"@types/metro-source-map@*": + version "0.76.0" + resolved "https://registry.yarnpkg.com/@types/metro-source-map/-/metro-source-map-0.76.0.tgz#c3b4bdd7c401b890165cf3274ffa3acc839cf191" + integrity sha512-nxx7MjnQJKzftTMDp6voMqdHjy4rL0gHeJHG2LYLcqdl9gs3sxeoAC1wx39SoeSYgsadWUvnj7GrJWMhP4oGvg== + +"@types/metro-transform-worker@*": + version "0.76.0" + resolved "https://registry.yarnpkg.com/@types/metro-transform-worker/-/metro-transform-worker-0.76.0.tgz#8b799647cabfa161ab0c13193b9c88fed2951668" + integrity sha512-jCpU73gb49YKKK8qtGzjMSh86HWG0IQiBgbUYU3WhXtReCVuA2Sy9sXXCiF9kZvnsqtRNbg2MR4ww8i1XEg/nw== + dependencies: + "@types/metro" "*" + "@types/metro-babel-transformer" "*" + "@types/metro-source-map" "*" + +"@types/metro@*", "@types/metro@^0.76.0": + version "0.76.0" + resolved "https://registry.yarnpkg.com/@types/metro/-/metro-0.76.0.tgz#fe6eadcab1444b3a0398aa1a9a87d09643d37879" + integrity sha512-3WIyw3e0QxF7XBvFuQIpBqui/7lYtFE8xpFIMKY+i+U9ERdbktBOEGXcN6gqG56BHq89502Ts5fxpOSrLEH3fQ== + dependencies: + "@types/babel__code-frame" "*" + "@types/metro-babel-transformer" "*" + "@types/metro-config" "*" + "@types/metro-core" "*" + "@types/metro-file-map" "*" + "@types/metro-resolver" "*" + "@types/metro-source-map" "*" + "@types/metro-transform-worker" "*" + "@types/ws" "*" + "@types/yargs" "*" + "@types/mime@*", "@types/mime@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" @@ -3009,6 +3087,13 @@ resolved "https://registry.yarnpkg.com/@types/wcwidth/-/wcwidth-1.0.0.tgz#a58f4673050f98c46ae8f852340889343b21a1f5" integrity sha512-X/WFfwGCIisEnd9EOSsX/jt7BHPDkcvQVYwVzc1nsE2K5bC56mWKnmNs0wyjcGcQsP7Wxq2zWSmhDDbF5Z7dDg== +"@types/ws@*": + version "8.5.4" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" + integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg== + dependencies: + "@types/node" "*" + "@types/ws@^7.4.7": version "7.4.7" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" @@ -3021,6 +3106,13 @@ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== +"@types/yargs@*": + version "17.0.22" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.22.tgz#7dd37697691b5f17d020f3c63e7a45971ff71e9a" + integrity sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g== + dependencies: + "@types/yargs-parser" "*" + "@types/yargs@^15.0.0": version "15.0.14" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06"