From d7db54deb77c8639b8aa7da29c07a66db40432f7 Mon Sep 17 00:00:00 2001 From: Zack Chapple Date: Tue, 27 Jan 2026 19:35:18 -0500 Subject: [PATCH 1/3] feat(core): adding rn 83 support --- packages/core/package.json | 10 +++++----- packages/core/src/commands/bundle-host/index.ts | 5 ++--- packages/core/src/commands/bundle-remote/index.ts | 5 ++--- packages/core/src/commands/utils/create-resolver.ts | 4 ++-- .../core/src/commands/utils/get-community-plugin.ts | 5 ++--- .../core/src/commands/utils/save-bundle-and-map.ts | 3 +-- packages/core/src/plugin/serializer.ts | 4 +--- packages/core/src/utils/vm-manager.ts | 10 +++++----- 8 files changed, 20 insertions(+), 26 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index bb1c632f..540051b6 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -52,11 +52,11 @@ }, "peerDependencies": { "@babel/types": "^7.25.0", - "metro": "^0.82.1", - "metro-config": "^0.82.1", - "metro-file-map": "^0.82.1", - "metro-resolver": "^0.82.1", - "metro-source-map": "^0.82.1", + "metro": "^0.82.1 || ^0.83.0", + "metro-config": "^0.82.1 || ^0.83.0", + "metro-file-map": "^0.82.1 || ^0.83.0", + "metro-resolver": "^0.82.1 || ^0.83.0", + "metro-source-map": "^0.82.1 || ^0.83.0", "react": ">=19.0.0", "react-native": ">=0.79.0" }, diff --git a/packages/core/src/commands/bundle-host/index.ts b/packages/core/src/commands/bundle-host/index.ts index 60fa7899..fcb15003 100644 --- a/packages/core/src/commands/bundle-host/index.ts +++ b/packages/core/src/commands/bundle-host/index.ts @@ -1,9 +1,8 @@ import path from 'node:path'; import util from 'node:util'; -import Server from 'metro/src/Server'; -import type { RequestOptions } from 'metro/src/shared/types'; import type { ModuleFederationConfigNormalized } from '../../types'; import { CLIError } from '../../utils/errors'; +import { Server, type RequestOptions } from '../../utils/metro-compat'; import type { Config } from '../types'; import { createResolver } from '../utils/create-resolver'; import { getCommunityCliPlugin } from '../utils/get-community-plugin'; @@ -54,7 +53,7 @@ async function bundleFederatedHost( communityCliPlugin.unstable_buildBundleWithConfig; return buildBundleWithConfig(args, config, { - build: async (server: Server, requestOpts: RequestOptions) => { + build: async (server: InstanceType, requestOpts: RequestOptions) => { // setup enhance middleware to trigger virtual modules setup config.server.enhanceMiddleware(server.processRequest, server); const resolver = await createResolver(server, args.platform); diff --git a/packages/core/src/commands/bundle-remote/index.ts b/packages/core/src/commands/bundle-remote/index.ts index 775dcd53..5ab8d657 100644 --- a/packages/core/src/commands/bundle-remote/index.ts +++ b/packages/core/src/commands/bundle-remote/index.ts @@ -3,10 +3,9 @@ import path from 'node:path'; import { pathToFileURL } from 'node:url'; import util from 'node:util'; import { mergeConfig } from 'metro'; -import Server from 'metro/src/Server'; -import type { OutputOptions, RequestOptions } from 'metro/src/shared/types'; import type { ModuleFederationConfigNormalized } from '../../types'; import { CLIError } from '../../utils/errors'; +import { Server, type OutputOptions, type RequestOptions } from '../../utils/metro-compat'; import type { Config } from '../types'; import { createModulePathRemapper } from '../utils/create-module-path-remapper'; import { createResolver } from '../utils/create-resolver'; @@ -39,7 +38,7 @@ interface BundleRequestOptions extends RequestOptions { sourceUrl: string; } -async function buildBundle(server: Server, requestOpts: BundleRequestOptions) { +async function buildBundle(server: InstanceType, requestOpts: BundleRequestOptions) { const bundle = await server.build({ ...Server.DEFAULT_BUNDLE_OPTIONS, ...requestOpts, diff --git a/packages/core/src/commands/utils/create-resolver.ts b/packages/core/src/commands/utils/create-resolver.ts index f12574a2..d1a1c874 100644 --- a/packages/core/src/commands/utils/create-resolver.ts +++ b/packages/core/src/commands/utils/create-resolver.ts @@ -1,4 +1,4 @@ -import type Server from 'metro/src/Server'; +import { Server } from '../../utils/metro-compat'; /** * Creates a resolver utility that mirrors Metro's bundling resolution behavior. @@ -14,7 +14,7 @@ import type Server from 'metro/src/Server'; * @param platform - The target platform for resolution (e.g., 'ios', 'android', null for default) * @returns The resolver object with a resolve method that takes source and target paths */ -export async function createResolver(server: Server, platform: string | null) { +export async function createResolver(server: InstanceType, platform: string | null) { const bundler = server.getBundler().getBundler(); const depGraph = await bundler.getDependencyGraph(); diff --git a/packages/core/src/commands/utils/get-community-plugin.ts b/packages/core/src/commands/utils/get-community-plugin.ts index 5cfa6dc5..e5d7fdbd 100644 --- a/packages/core/src/commands/utils/get-community-plugin.ts +++ b/packages/core/src/commands/utils/get-community-plugin.ts @@ -1,7 +1,6 @@ import type { ConfigT } from 'metro-config'; -import type Server from 'metro/src/Server'; -import type { OutputOptions, RequestOptions } from 'metro/src/shared/types'; import { CLIError } from '../../utils/errors'; +import { Server, type OutputOptions, type RequestOptions } from '../../utils/metro-compat'; interface Command { name: string; @@ -21,7 +20,7 @@ interface CommunityCliPlugin { config: ConfigT, bundleImpl: { build: ( - server: Server, + server: InstanceType, requestOpts: RequestOptions ) => Promise<{ code: string; map: string }>; save: ( diff --git a/packages/core/src/commands/utils/save-bundle-and-map.ts b/packages/core/src/commands/utils/save-bundle-and-map.ts index 9af40eef..ec1864dc 100644 --- a/packages/core/src/commands/utils/save-bundle-and-map.ts +++ b/packages/core/src/commands/utils/save-bundle-and-map.ts @@ -1,8 +1,7 @@ import { promises as fs } from 'node:fs'; import util from 'node:util'; import type { MixedSourceMap } from 'metro-source-map'; -import relativizeSourceMapInline from 'metro/src/lib/relativizeSourceMap'; -import type { OutputOptions } from 'metro/src/shared/types'; +import { relativizeSourceMapInline, type OutputOptions } from '../../utils/metro-compat'; function relativizeSerializedMap( map: string, diff --git a/packages/core/src/plugin/serializer.ts b/packages/core/src/plugin/serializer.ts index 7742bcd8..fa93a78a 100644 --- a/packages/core/src/plugin/serializer.ts +++ b/packages/core/src/plugin/serializer.ts @@ -1,11 +1,9 @@ import path from 'node:path'; import type { Module, ReadOnlyGraph, SerializerOptions } from 'metro'; import type { SerializerConfigT } from 'metro-config'; -import baseJSBundle from 'metro/src/DeltaBundler/Serializers/baseJSBundle'; -import CountingSet from 'metro/src/lib/CountingSet'; -import bundleToString from 'metro/src/lib/bundleToString'; import type { ModuleFederationConfigNormalized, Shared } from '../types'; import { ConfigError } from '../utils/errors'; +import { baseJSBundle, CountingSet, bundleToString } from '../utils/metro-compat'; type CustomSerializer = SerializerConfigT['customSerializer']; diff --git a/packages/core/src/utils/vm-manager.ts b/packages/core/src/utils/vm-manager.ts index 497f4a5e..53099b75 100644 --- a/packages/core/src/utils/vm-manager.ts +++ b/packages/core/src/utils/vm-manager.ts @@ -6,11 +6,11 @@ import type { TransformerConfigT, } from 'metro-config'; import type { FileSystem } from 'metro-file-map'; -import type MetroServer from 'metro/src/Server'; +import { Server as MetroServer } from './metro-compat'; type EnhanceMiddleware = ServerConfigT['enhanceMiddleware']; type GetTransformOptions = TransformerConfigT['getTransformOptions']; -type Bundler = ReturnType['getBundler']>; +type Bundler = ReturnType['getBundler']>['getBundler']>; export class VirtualModuleManager { private setupFinished: Promise | null = null; @@ -69,8 +69,8 @@ export class VirtualModuleManager { setup(bundler: Bundler) { this.setupFinished = (async () => { const graph = await bundler.getDependencyGraph(); - // @ts-expect-error incomplete types - this.ensureFileSystemPatched(graph._fileSystem); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.ensureFileSystemPatched((graph as any)._fileSystem); this.ensureBundlerPatched(bundler); return true; })(); @@ -104,7 +104,7 @@ export class VirtualModuleManager { } const transformFile = bundler.transformFile.bind(bundler); - bundler.transformFile = async (filePath, transformOptions, fileBuffer) => { + bundler.transformFile = async (filePath: string, transformOptions: any, fileBuffer?: Buffer) => { let buffer = fileBuffer; const virtualModule = this.virtualModules.get(filePath); From 36efaa41db633b4b13e16b51af8a2261a25cd080 Mon Sep 17 00:00:00 2001 From: Zack Chapple Date: Tue, 27 Jan 2026 19:46:11 -0500 Subject: [PATCH 2/3] feat(core): adding rn 83 support --- packages/core/src/commands/bundle-host/index.ts | 7 +++++-- packages/core/src/commands/bundle-remote/index.ts | 11 +++++++++-- packages/core/src/commands/utils/create-resolver.ts | 7 +++++-- .../core/src/commands/utils/get-community-plugin.ts | 6 +++++- .../core/src/commands/utils/save-bundle-and-map.ts | 5 ++++- packages/core/src/plugin/serializer.ts | 6 +++++- packages/core/src/utils/vm-manager.ts | 12 +++++++++--- 7 files changed, 42 insertions(+), 12 deletions(-) diff --git a/packages/core/src/commands/bundle-host/index.ts b/packages/core/src/commands/bundle-host/index.ts index fcb15003..60c1f882 100644 --- a/packages/core/src/commands/bundle-host/index.ts +++ b/packages/core/src/commands/bundle-host/index.ts @@ -2,7 +2,7 @@ import path from 'node:path'; import util from 'node:util'; import type { ModuleFederationConfigNormalized } from '../../types'; import { CLIError } from '../../utils/errors'; -import { Server, type RequestOptions } from '../../utils/metro-compat'; +import { type RequestOptions, Server } from '../../utils/metro-compat'; import type { Config } from '../types'; import { createResolver } from '../utils/create-resolver'; import { getCommunityCliPlugin } from '../utils/get-community-plugin'; @@ -53,7 +53,10 @@ async function bundleFederatedHost( communityCliPlugin.unstable_buildBundleWithConfig; return buildBundleWithConfig(args, config, { - build: async (server: InstanceType, requestOpts: RequestOptions) => { + build: async ( + server: InstanceType, + requestOpts: RequestOptions + ) => { // setup enhance middleware to trigger virtual modules setup config.server.enhanceMiddleware(server.processRequest, server); const resolver = await createResolver(server, args.platform); diff --git a/packages/core/src/commands/bundle-remote/index.ts b/packages/core/src/commands/bundle-remote/index.ts index 5ab8d657..025c4ebf 100644 --- a/packages/core/src/commands/bundle-remote/index.ts +++ b/packages/core/src/commands/bundle-remote/index.ts @@ -5,7 +5,11 @@ import util from 'node:util'; import { mergeConfig } from 'metro'; import type { ModuleFederationConfigNormalized } from '../../types'; import { CLIError } from '../../utils/errors'; -import { Server, type OutputOptions, type RequestOptions } from '../../utils/metro-compat'; +import { + type OutputOptions, + type RequestOptions, + Server, +} from '../../utils/metro-compat'; import type { Config } from '../types'; import { createModulePathRemapper } from '../utils/create-module-path-remapper'; import { createResolver } from '../utils/create-resolver'; @@ -38,7 +42,10 @@ interface BundleRequestOptions extends RequestOptions { sourceUrl: string; } -async function buildBundle(server: InstanceType, requestOpts: BundleRequestOptions) { +async function buildBundle( + server: InstanceType, + requestOpts: BundleRequestOptions +) { const bundle = await server.build({ ...Server.DEFAULT_BUNDLE_OPTIONS, ...requestOpts, diff --git a/packages/core/src/commands/utils/create-resolver.ts b/packages/core/src/commands/utils/create-resolver.ts index d1a1c874..3553ebf5 100644 --- a/packages/core/src/commands/utils/create-resolver.ts +++ b/packages/core/src/commands/utils/create-resolver.ts @@ -1,4 +1,4 @@ -import { Server } from '../../utils/metro-compat'; +import type { Server } from '../../utils/metro-compat'; /** * Creates a resolver utility that mirrors Metro's bundling resolution behavior. @@ -14,7 +14,10 @@ import { Server } from '../../utils/metro-compat'; * @param platform - The target platform for resolution (e.g., 'ios', 'android', null for default) * @returns The resolver object with a resolve method that takes source and target paths */ -export async function createResolver(server: InstanceType, platform: string | null) { +export async function createResolver( + server: InstanceType, + platform: string | null +) { const bundler = server.getBundler().getBundler(); const depGraph = await bundler.getDependencyGraph(); diff --git a/packages/core/src/commands/utils/get-community-plugin.ts b/packages/core/src/commands/utils/get-community-plugin.ts index e5d7fdbd..30ba5fe2 100644 --- a/packages/core/src/commands/utils/get-community-plugin.ts +++ b/packages/core/src/commands/utils/get-community-plugin.ts @@ -1,6 +1,10 @@ import type { ConfigT } from 'metro-config'; import { CLIError } from '../../utils/errors'; -import { Server, type OutputOptions, type RequestOptions } from '../../utils/metro-compat'; +import type { + OutputOptions, + RequestOptions, + Server, +} from '../../utils/metro-compat'; interface Command { name: string; diff --git a/packages/core/src/commands/utils/save-bundle-and-map.ts b/packages/core/src/commands/utils/save-bundle-and-map.ts index ec1864dc..6c3b1da4 100644 --- a/packages/core/src/commands/utils/save-bundle-and-map.ts +++ b/packages/core/src/commands/utils/save-bundle-and-map.ts @@ -1,7 +1,10 @@ import { promises as fs } from 'node:fs'; import util from 'node:util'; import type { MixedSourceMap } from 'metro-source-map'; -import { relativizeSourceMapInline, type OutputOptions } from '../../utils/metro-compat'; +import { + type OutputOptions, + relativizeSourceMapInline, +} from '../../utils/metro-compat'; function relativizeSerializedMap( map: string, diff --git a/packages/core/src/plugin/serializer.ts b/packages/core/src/plugin/serializer.ts index fa93a78a..77a5b949 100644 --- a/packages/core/src/plugin/serializer.ts +++ b/packages/core/src/plugin/serializer.ts @@ -3,7 +3,11 @@ import type { Module, ReadOnlyGraph, SerializerOptions } from 'metro'; import type { SerializerConfigT } from 'metro-config'; import type { ModuleFederationConfigNormalized, Shared } from '../types'; import { ConfigError } from '../utils/errors'; -import { baseJSBundle, CountingSet, bundleToString } from '../utils/metro-compat'; +import { + CountingSet, + baseJSBundle, + bundleToString, +} from '../utils/metro-compat'; type CustomSerializer = SerializerConfigT['customSerializer']; diff --git a/packages/core/src/utils/vm-manager.ts b/packages/core/src/utils/vm-manager.ts index 53099b75..dfeb40e6 100644 --- a/packages/core/src/utils/vm-manager.ts +++ b/packages/core/src/utils/vm-manager.ts @@ -6,11 +6,13 @@ import type { TransformerConfigT, } from 'metro-config'; import type { FileSystem } from 'metro-file-map'; -import { Server as MetroServer } from './metro-compat'; +import type { Server as MetroServer } from './metro-compat'; type EnhanceMiddleware = ServerConfigT['enhanceMiddleware']; type GetTransformOptions = TransformerConfigT['getTransformOptions']; -type Bundler = ReturnType['getBundler']>['getBundler']>; +type Bundler = ReturnType< + ReturnType['getBundler']>['getBundler'] +>; export class VirtualModuleManager { private setupFinished: Promise | null = null; @@ -104,7 +106,11 @@ export class VirtualModuleManager { } const transformFile = bundler.transformFile.bind(bundler); - bundler.transformFile = async (filePath: string, transformOptions: any, fileBuffer?: Buffer) => { + bundler.transformFile = async ( + filePath: string, + transformOptions: any, + fileBuffer?: Buffer + ) => { let buffer = fileBuffer; const virtualModule = this.virtualModules.get(filePath); From 0932fbe2371943814b7ed60cee25f2812326a9f7 Mon Sep 17 00:00:00 2001 From: Zack Chapple Date: Thu, 29 Jan 2026 15:41:40 -0500 Subject: [PATCH 3/3] feat(core): adding rn 83 support --- packages/core/src/utils/metro-compat.ts | 55 +++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 packages/core/src/utils/metro-compat.ts diff --git a/packages/core/src/utils/metro-compat.ts b/packages/core/src/utils/metro-compat.ts new file mode 100644 index 00000000..515b3a41 --- /dev/null +++ b/packages/core/src/utils/metro-compat.ts @@ -0,0 +1,55 @@ +/** + * Metro Compatibility Layer + * + * Provides backwards-compatible imports for Metro 0.82 and 0.83+ + * + * Metro 0.83 introduced a restrictive `exports` field that only allows + * `metro/private/*` paths instead of direct `metro/src/*` imports. + * + * This module dynamically resolves the correct import path based on the + * installed Metro version, ensuring compatibility with both versions. + */ + +/** + * Attempts to import from Metro 0.83 format first, falls back to 0.82 format + */ +function tryImport(metro83Path: string, metro82Path: string) { + try { + return require(metro83Path); + } catch { + return require(metro82Path); + } +} + +// Server class +export const Server = tryImport( + 'metro/private/Server', + 'metro/src/Server' +).default; + +// DeltaBundler Serializers +export const baseJSBundle = tryImport( + 'metro/private/DeltaBundler/Serializers/baseJSBundle', + 'metro/src/DeltaBundler/Serializers/baseJSBundle' +).default; + +// Utility classes +export const CountingSet = tryImport( + 'metro/private/lib/CountingSet', + 'metro/src/lib/CountingSet' +).default; + +// Bundle utilities +export const bundleToString = tryImport( + 'metro/private/lib/bundleToString', + 'metro/src/lib/bundleToString' +).default; + +export const relativizeSourceMapInline = tryImport( + 'metro/private/lib/relativizeSourceMap', + 'metro/src/lib/relativizeSourceMap' +).relativizeSourceMapInline; + +// Re-export types - these come from metro/src/shared/types in both versions +// The types themselves are available through the main 'metro' package export +export type { RequestOptions, OutputOptions } from 'metro/src/shared/types';