@module-federation/metro 0.0.0-fix-loop-load-20260203135642 → 0.0.0-fix-array-share-scope-20260225123251

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/commands/bundle-host/index.js +2 -3
  2. package/dist/commands/bundle-host/index.mjs +2 -25
  3. package/dist/commands/bundle-remote/index.js +3 -4
  4. package/dist/commands/bundle-remote/index.mjs +3 -25
  5. package/dist/commands/utils/create-resolver.d.ts +1 -1
  6. package/dist/commands/utils/get-community-plugin.d.ts +1 -2
  7. package/dist/commands/utils/get-community-plugin.js +3 -4
  8. package/dist/commands/utils/get-community-plugin.mjs +3 -4
  9. package/dist/commands/utils/save-bundle-and-map.d.ts +1 -1
  10. package/dist/commands/utils/save-bundle-and-map.js +2 -3
  11. package/dist/commands/utils/save-bundle-and-map.mjs +2 -25
  12. package/dist/logger.d.ts +2 -0
  13. package/dist/logger.js +39 -0
  14. package/dist/logger.mjs +7 -0
  15. package/dist/modules/asyncRequire.ts +0 -3
  16. package/dist/modules/asyncStartup.tsx +1 -0
  17. package/dist/modules/metroCorePlugin.ts +3 -3
  18. package/dist/plugin/constants.d.ts +1 -0
  19. package/dist/plugin/constants.js +4 -0
  20. package/dist/plugin/constants.mjs +2 -1
  21. package/dist/plugin/manifest.js +8 -2
  22. package/dist/plugin/manifest.mjs +8 -2
  23. package/dist/plugin/normalize-options.js +43 -5
  24. package/dist/plugin/normalize-options.mjs +43 -5
  25. package/dist/plugin/serializer.js +3 -8
  26. package/dist/plugin/serializer.mjs +3 -30
  27. package/dist/plugin/validate-options.js +92 -3
  28. package/dist/plugin/validate-options.mjs +82 -3
  29. package/dist/types.d.ts +14 -15
  30. package/dist/utils/metro-compat.d.ts +23 -0
  31. package/dist/utils/metro-compat.js +70 -0
  32. package/dist/utils/metro-compat.mjs +26 -0
  33. package/dist/utils/vm-manager.d.ts +1 -1
  34. package/package.json +6 -3
@@ -40,9 +40,8 @@ const external_node_path_namespaceObject = require("node:path");
40
40
  var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
41
41
  const external_node_util_namespaceObject = require("node:util");
42
42
  var external_node_util_default = /*#__PURE__*/ __webpack_require__.n(external_node_util_namespaceObject);
43
- const Server_namespaceObject = require("metro/src/Server");
44
- var Server_default = /*#__PURE__*/ __webpack_require__.n(Server_namespaceObject);
45
43
  const errors_js_namespaceObject = require("../../utils/errors.js");
44
+ const metro_compat_js_namespaceObject = require("../../utils/metro-compat.js");
46
45
  const create_resolver_js_namespaceObject = require("../utils/create-resolver.js");
47
46
  const get_community_plugin_js_namespaceObject = require("../utils/get-community-plugin.js");
48
47
  const load_metro_config_js_namespaceObject = require("../utils/load-metro-config.js");
@@ -75,7 +74,7 @@ async function bundleFederatedHost(_argv, cfg, args) {
75
74
  to: `./${external_node_path_default().relative(config.projectRoot, hostEntryFilepath)}`
76
75
  });
77
76
  return server.build({
78
- ...Server_default().DEFAULT_BUNDLE_OPTIONS,
77
+ ...metro_compat_js_namespaceObject.Server.DEFAULT_BUNDLE_OPTIONS,
79
78
  ...requestOpts
80
79
  });
81
80
  },
@@ -3,35 +3,12 @@ import 'module';
3
3
  import node_path from "node:path";
4
4
  import node_util from "node:util";
5
5
  import { CLIError } from "../../utils/errors.mjs";
6
+ import { Server } from "../../utils/metro-compat.mjs";
6
7
  import { createResolver } from "../utils/create-resolver.mjs";
7
8
  import { getCommunityCliPlugin } from "../utils/get-community-plugin.mjs";
8
9
  import load_metro_config from "../utils/load-metro-config.mjs";
9
10
  import { saveBundleAndMap } from "../utils/save-bundle-and-map.mjs";
10
11
  import options from "./options.mjs";
11
- import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "node:module";
12
- var __webpack_require__ = {};
13
- (()=>{
14
- __webpack_require__.n = (module)=>{
15
- var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
16
- __webpack_require__.d(getter, {
17
- a: getter
18
- });
19
- return getter;
20
- };
21
- })();
22
- (()=>{
23
- __webpack_require__.d = (exports, definition)=>{
24
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
25
- enumerable: true,
26
- get: definition[key]
27
- });
28
- };
29
- })();
30
- (()=>{
31
- __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
32
- })();
33
- const Server_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("metro/src/Server");
34
- var Server_default = /*#__PURE__*/ __webpack_require__.n(Server_namespaceObject);
35
12
  async function bundleFederatedHost(_argv, cfg, args) {
36
13
  const logger = cfg.logger ?? console;
37
14
  global.__METRO_FEDERATION_ORIGINAL_ENTRY_PATH = args.entryFile;
@@ -57,7 +34,7 @@ async function bundleFederatedHost(_argv, cfg, args) {
57
34
  to: `./${node_path.relative(config.projectRoot, hostEntryFilepath)}`
58
35
  });
59
36
  return server.build({
60
- ...Server_default().DEFAULT_BUNDLE_OPTIONS,
37
+ ...Server.DEFAULT_BUNDLE_OPTIONS,
61
38
  ...requestOpts
62
39
  });
63
40
  },
@@ -43,9 +43,8 @@ const external_node_url_namespaceObject = require("node:url");
43
43
  const external_node_util_namespaceObject = require("node:util");
44
44
  var external_node_util_default = /*#__PURE__*/ __webpack_require__.n(external_node_util_namespaceObject);
45
45
  const external_metro_namespaceObject = require("metro");
46
- const Server_namespaceObject = require("metro/src/Server");
47
- var Server_default = /*#__PURE__*/ __webpack_require__.n(Server_namespaceObject);
48
46
  const errors_js_namespaceObject = require("../../utils/errors.js");
47
+ const metro_compat_js_namespaceObject = require("../../utils/metro-compat.js");
49
48
  const create_module_path_remapper_js_namespaceObject = require("../utils/create-module-path-remapper.js");
50
49
  const create_resolver_js_namespaceObject = require("../utils/create-resolver.js");
51
50
  const load_metro_config_js_namespaceObject = require("../utils/load-metro-config.js");
@@ -56,7 +55,7 @@ var external_options_js_default = /*#__PURE__*/ __webpack_require__.n(external_o
56
55
  const DEFAULT_OUTPUT = 'dist';
57
56
  async function buildBundle(server, requestOpts) {
58
57
  const bundle = await server.build({
59
- ...Server_default().DEFAULT_BUNDLE_OPTIONS,
58
+ ...metro_compat_js_namespaceObject.Server.DEFAULT_BUNDLE_OPTIONS,
60
59
  ...requestOpts
61
60
  });
62
61
  return bundle;
@@ -132,7 +131,7 @@ async function bundleFederatedRemote(_argv, cfg, args) {
132
131
  }
133
132
  }
134
133
  });
135
- const server = new (Server_default())(config);
134
+ const server = new metro_compat_js_namespaceObject.Server(config);
136
135
  config.server.enhanceMiddleware(server.processRequest, server);
137
136
  const resolver = await (0, create_resolver_js_namespaceObject.createResolver)(server, args.platform);
138
137
  const outputDir = args.output ? external_node_path_default().resolve(external_node_path_default().join(args.output, args.platform)) : external_node_path_default().resolve(config.projectRoot, external_node_path_default().join(DEFAULT_OUTPUT, args.platform));
@@ -5,40 +5,18 @@ import node_path from "node:path";
5
5
  import { pathToFileURL } from "node:url";
6
6
  import node_util from "node:util";
7
7
  import { CLIError } from "../../utils/errors.mjs";
8
+ import { Server } from "../../utils/metro-compat.mjs";
8
9
  import { createModulePathRemapper } from "../utils/create-module-path-remapper.mjs";
9
10
  import { createResolver } from "../utils/create-resolver.mjs";
10
11
  import load_metro_config from "../utils/load-metro-config.mjs";
11
12
  import { saveBundleAndMap } from "../utils/save-bundle-and-map.mjs";
12
13
  import options from "./options.mjs";
13
14
  import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "node:module";
14
- var __webpack_require__ = {};
15
- (()=>{
16
- __webpack_require__.n = (module)=>{
17
- var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
18
- __webpack_require__.d(getter, {
19
- a: getter
20
- });
21
- return getter;
22
- };
23
- })();
24
- (()=>{
25
- __webpack_require__.d = (exports, definition)=>{
26
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
27
- enumerable: true,
28
- get: definition[key]
29
- });
30
- };
31
- })();
32
- (()=>{
33
- __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
34
- })();
35
15
  const external_metro_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("metro");
36
- const Server_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("metro/src/Server");
37
- var Server_default = /*#__PURE__*/ __webpack_require__.n(Server_namespaceObject);
38
16
  const DEFAULT_OUTPUT = 'dist';
39
17
  async function buildBundle(server, requestOpts) {
40
18
  const bundle = await server.build({
41
- ...Server_default().DEFAULT_BUNDLE_OPTIONS,
19
+ ...Server.DEFAULT_BUNDLE_OPTIONS,
42
20
  ...requestOpts
43
21
  });
44
22
  return bundle;
@@ -114,7 +92,7 @@ async function bundleFederatedRemote(_argv, cfg, args) {
114
92
  }
115
93
  }
116
94
  });
117
- const server = new (Server_default())(config);
95
+ const server = new Server(config);
118
96
  config.server.enhanceMiddleware(server.processRequest, server);
119
97
  const resolver = await createResolver(server, args.platform);
120
98
  const outputDir = args.output ? node_path.resolve(node_path.join(args.output, args.platform)) : node_path.resolve(config.projectRoot, node_path.join(DEFAULT_OUTPUT, args.platform));
@@ -1,4 +1,4 @@
1
- import type Server from 'metro/src/Server';
1
+ import type { Server } from '../../utils/metro-compat';
2
2
  /**
3
3
  * Creates a resolver utility that mirrors Metro's bundling resolution behavior.
4
4
  * This utility exposes Metro's internal resolver to the command context,
@@ -1,6 +1,5 @@
1
1
  import type { ConfigT } from 'metro-config';
2
- import type Server from 'metro/src/Server';
3
- import type { OutputOptions, RequestOptions } from 'metro/src/shared/types';
2
+ import type { OutputOptions, RequestOptions, Server } from '../../utils/metro-compat';
4
3
  interface Command {
5
4
  name: string;
6
5
  description: string;
@@ -28,18 +28,17 @@ __webpack_require__.d(__webpack_exports__, {
28
28
  });
29
29
  const errors_js_namespaceObject = require("../../utils/errors.js");
30
30
  function getCommunityCliPlugin(reactNativePath) {
31
- let communityCliPlugin;
31
+ let communityCliPluginPath;
32
32
  try {
33
- const communityCliPluginPath = require.resolve('@react-native/community-cli-plugin', {
33
+ communityCliPluginPath = require.resolve('@react-native/community-cli-plugin', {
34
34
  paths: [
35
35
  reactNativePath ?? require.resolve('react-native')
36
36
  ]
37
37
  });
38
- communityCliPlugin = require(communityCliPluginPath);
39
38
  } catch {
40
39
  throw new errors_js_namespaceObject.CLIError('Community CLI plugin is not installed.');
41
40
  }
42
- return communityCliPlugin;
41
+ return require(communityCliPluginPath);
43
42
  }
44
43
  exports.getCommunityCliPlugin = __webpack_exports__.getCommunityCliPlugin;
45
44
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
@@ -2,17 +2,16 @@ import __rslib_shim_module__ from 'module';
2
2
  const require = /*#__PURE__*/ __rslib_shim_module__.createRequire(import.meta.url);
3
3
  import { CLIError } from "../../utils/errors.mjs";
4
4
  function getCommunityCliPlugin(reactNativePath) {
5
- let communityCliPlugin;
5
+ let communityCliPluginPath;
6
6
  try {
7
- const communityCliPluginPath = require.resolve('@react-native/community-cli-plugin', {
7
+ communityCliPluginPath = require.resolve('@react-native/community-cli-plugin', {
8
8
  paths: [
9
9
  reactNativePath ?? require.resolve('react-native')
10
10
  ]
11
11
  });
12
- communityCliPlugin = require(communityCliPluginPath);
13
12
  } catch {
14
13
  throw new CLIError('Community CLI plugin is not installed.');
15
14
  }
16
- return communityCliPlugin;
15
+ return require(communityCliPluginPath);
17
16
  }
18
17
  export { getCommunityCliPlugin };
@@ -1,4 +1,4 @@
1
- import type { OutputOptions } from 'metro/src/shared/types';
1
+ import type { OutputOptions } from '../../utils/metro-compat';
2
2
  export declare function saveBundleAndMap(bundle: {
3
3
  code: string;
4
4
  map: string;
@@ -38,11 +38,10 @@ __webpack_require__.d(__webpack_exports__, {
38
38
  const external_node_fs_namespaceObject = require("node:fs");
39
39
  const external_node_util_namespaceObject = require("node:util");
40
40
  var external_node_util_default = /*#__PURE__*/ __webpack_require__.n(external_node_util_namespaceObject);
41
- const relativizeSourceMap_namespaceObject = require("metro/src/lib/relativizeSourceMap");
42
- var relativizeSourceMap_default = /*#__PURE__*/ __webpack_require__.n(relativizeSourceMap_namespaceObject);
41
+ const metro_compat_js_namespaceObject = require("../../utils/metro-compat.js");
43
42
  function relativizeSerializedMap(map, sourceMapSourcesRoot) {
44
43
  const sourceMap = JSON.parse(map);
45
- relativizeSourceMap_default()(sourceMap, sourceMapSourcesRoot);
44
+ (0, metro_compat_js_namespaceObject.relativizeSourceMapInline)(sourceMap, sourceMapSourcesRoot);
46
45
  return JSON.stringify(sourceMap);
47
46
  }
48
47
  async function saveBundleAndMap(bundle, options, log) {
@@ -2,33 +2,10 @@ import 'module';
2
2
  /*#__PURE__*/ import.meta.url;
3
3
  import { promises } from "node:fs";
4
4
  import node_util from "node:util";
5
- import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "node:module";
6
- var __webpack_require__ = {};
7
- (()=>{
8
- __webpack_require__.n = (module)=>{
9
- var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
10
- __webpack_require__.d(getter, {
11
- a: getter
12
- });
13
- return getter;
14
- };
15
- })();
16
- (()=>{
17
- __webpack_require__.d = (exports, definition)=>{
18
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
19
- enumerable: true,
20
- get: definition[key]
21
- });
22
- };
23
- })();
24
- (()=>{
25
- __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
26
- })();
27
- const relativizeSourceMap_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("metro/src/lib/relativizeSourceMap");
28
- var relativizeSourceMap_default = /*#__PURE__*/ __webpack_require__.n(relativizeSourceMap_namespaceObject);
5
+ import { relativizeSourceMapInline } from "../../utils/metro-compat.mjs";
29
6
  function relativizeSerializedMap(map, sourceMapSourcesRoot) {
30
7
  const sourceMap = JSON.parse(map);
31
- relativizeSourceMap_default()(sourceMap, sourceMapSourcesRoot);
8
+ relativizeSourceMapInline(sourceMap, sourceMapSourcesRoot);
32
9
  return JSON.stringify(sourceMap);
33
10
  }
34
11
  async function saveBundleAndMap(bundle, options, log) {
@@ -0,0 +1,2 @@
1
+ declare const logger: import("@module-federation/sdk").Logger;
2
+ export default logger;
package/dist/logger.js ADDED
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ default: ()=>src_logger
28
+ });
29
+ const sdk_namespaceObject = require("@module-federation/sdk");
30
+ const constants_js_namespaceObject = require("./plugin/constants.js");
31
+ const logger = (0, sdk_namespaceObject.createLogger)(constants_js_namespaceObject.PLUGIN_IDENTIFIER);
32
+ const src_logger = logger;
33
+ exports["default"] = __webpack_exports__["default"];
34
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
35
+ "default"
36
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
37
+ Object.defineProperty(exports, '__esModule', {
38
+ value: true
39
+ });
@@ -0,0 +1,7 @@
1
+ import 'module';
2
+ /*#__PURE__*/ import.meta.url;
3
+ import { createLogger } from "@module-federation/sdk";
4
+ import { PLUGIN_IDENTIFIER } from "./plugin/constants.mjs";
5
+ const logger = createLogger(PLUGIN_IDENTIFIER);
6
+ const src_logger = logger;
7
+ export { src_logger as default };
@@ -65,7 +65,6 @@ function buildLoadBundleAsyncWrapper() {
65
65
  const registry = require('mf:remote-module-registry');
66
66
 
67
67
  const __loadBundleAsync =
68
- // @ts-expect-error dynamic key access on global object
69
68
  globalThis[`${__METRO_GLOBAL_PREFIX__ ?? ''}__loadBundleAsync`];
70
69
 
71
70
  const loadBundleAsync =
@@ -125,10 +124,8 @@ if (!process.env.EXPO_OS) {
125
124
  buildAsyncRequire,
126
125
  } = require('@expo/metro-runtime/src/async-require/buildAsyncRequire');
127
126
 
128
- // @ts-expect-error dynamic key access on global object
129
127
  global[`${__METRO_GLOBAL_PREFIX__}__loadBundleAsync`] = buildAsyncRequire();
130
128
  }
131
129
 
132
- // @ts-expect-error dynamic key access on global object
133
130
  global[`${__METRO_GLOBAL_PREFIX__}__loadBundleAsync`] =
134
131
  buildLoadBundleAsyncWrapper();
@@ -2,6 +2,7 @@ import type { Federation } from '@module-federation/runtime';
2
2
  import React from 'react';
3
3
 
4
4
  declare global {
5
+ // @ts-expect-error -- Intentional redeclaration for Metro/React Native runtime global.
5
6
  // eslint-disable-next-line no-var
6
7
  var __DEV__: boolean;
7
8
  // eslint-disable-next-line no-var
@@ -1,9 +1,10 @@
1
1
  import type {
2
2
  Federation,
3
- FederationRuntimePlugin,
3
+ ModuleFederationRuntimePlugin,
4
4
  } from '@module-federation/runtime';
5
5
 
6
6
  declare global {
7
+ // @ts-expect-error -- Intentional redeclaration for Metro/React Native runtime global.
7
8
  // eslint-disable-next-line no-var
8
9
  var __DEV__: boolean;
9
10
  // eslint-disable-next-line no-var
@@ -42,13 +43,12 @@ const buildUrlForEntryBundle = (entry: string) => {
42
43
  return entry;
43
44
  };
44
45
 
45
- const MetroCorePlugin: () => FederationRuntimePlugin = () => ({
46
+ const MetroCorePlugin: () => ModuleFederationRuntimePlugin = () => ({
46
47
  name: 'metro-core-plugin',
47
48
  loadEntry: async ({ remoteInfo }) => {
48
49
  const { entry, entryGlobalName } = remoteInfo;
49
50
 
50
51
  const __loadBundleAsync =
51
- // @ts-expect-error dynamic key access on global object
52
52
  globalThis[`${__METRO_GLOBAL_PREFIX__ ?? ''}__loadBundleAsync`];
53
53
 
54
54
  const loadBundleAsync =
@@ -2,6 +2,7 @@ export declare const INIT_HOST = "mf:init-host";
2
2
  export declare const ASYNC_REQUIRE = "mf:async-require";
3
3
  export declare const REMOTE_MODULE_REGISTRY = "mf:remote-module-registry";
4
4
  export declare const REMOTE_HMR_SETUP = "mf:remote-hmr";
5
+ export declare const PLUGIN_IDENTIFIER = "[ Module Federation Metro ]";
5
6
  export declare const DEFAULT_ENTRY_FILENAME = "remoteEntry.bundle";
6
7
  export declare const GET_DEV_SERVER_REGEX: RegExp;
7
8
  export declare const HMR_CLIENT_REGEX: RegExp;
@@ -30,6 +30,7 @@ __webpack_require__.d(__webpack_exports__, {
30
30
  HMR_CLIENT_REGEX: ()=>HMR_CLIENT_REGEX,
31
31
  INIT_HOST: ()=>INIT_HOST,
32
32
  MANIFEST_FILENAME: ()=>MANIFEST_FILENAME,
33
+ PLUGIN_IDENTIFIER: ()=>PLUGIN_IDENTIFIER,
33
34
  REMOTE_HMR_SETUP: ()=>REMOTE_HMR_SETUP,
34
35
  REMOTE_MODULE_REGISTRY: ()=>REMOTE_MODULE_REGISTRY,
35
36
  TMP_DIR_NAME: ()=>TMP_DIR_NAME
@@ -38,6 +39,7 @@ const INIT_HOST = 'mf:init-host';
38
39
  const ASYNC_REQUIRE = 'mf:async-require';
39
40
  const REMOTE_MODULE_REGISTRY = 'mf:remote-module-registry';
40
41
  const REMOTE_HMR_SETUP = 'mf:remote-hmr';
42
+ const PLUGIN_IDENTIFIER = '[ Module Federation Metro ]';
41
43
  const DEFAULT_ENTRY_FILENAME = 'remoteEntry.bundle';
42
44
  const GET_DEV_SERVER_REGEX = /react-native\/Libraries\/Core\/Devtools\/getDevServer\.js$/;
43
45
  const HMR_CLIENT_REGEX = /react-native\/Libraries\/Utilities\/HMRClient\.js$/;
@@ -49,6 +51,7 @@ exports.GET_DEV_SERVER_REGEX = __webpack_exports__.GET_DEV_SERVER_REGEX;
49
51
  exports.HMR_CLIENT_REGEX = __webpack_exports__.HMR_CLIENT_REGEX;
50
52
  exports.INIT_HOST = __webpack_exports__.INIT_HOST;
51
53
  exports.MANIFEST_FILENAME = __webpack_exports__.MANIFEST_FILENAME;
54
+ exports.PLUGIN_IDENTIFIER = __webpack_exports__.PLUGIN_IDENTIFIER;
52
55
  exports.REMOTE_HMR_SETUP = __webpack_exports__.REMOTE_HMR_SETUP;
53
56
  exports.REMOTE_MODULE_REGISTRY = __webpack_exports__.REMOTE_MODULE_REGISTRY;
54
57
  exports.TMP_DIR_NAME = __webpack_exports__.TMP_DIR_NAME;
@@ -59,6 +62,7 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
59
62
  "HMR_CLIENT_REGEX",
60
63
  "INIT_HOST",
61
64
  "MANIFEST_FILENAME",
65
+ "PLUGIN_IDENTIFIER",
62
66
  "REMOTE_HMR_SETUP",
63
67
  "REMOTE_MODULE_REGISTRY",
64
68
  "TMP_DIR_NAME"
@@ -4,9 +4,10 @@ const INIT_HOST = 'mf:init-host';
4
4
  const ASYNC_REQUIRE = 'mf:async-require';
5
5
  const REMOTE_MODULE_REGISTRY = 'mf:remote-module-registry';
6
6
  const REMOTE_HMR_SETUP = 'mf:remote-hmr';
7
+ const PLUGIN_IDENTIFIER = '[ Module Federation Metro ]';
7
8
  const DEFAULT_ENTRY_FILENAME = 'remoteEntry.bundle';
8
9
  const GET_DEV_SERVER_REGEX = /react-native\/Libraries\/Core\/Devtools\/getDevServer\.js$/;
9
10
  const HMR_CLIENT_REGEX = /react-native\/Libraries\/Utilities\/HMRClient\.js$/;
10
11
  const TMP_DIR_NAME = '.mf-metro';
11
12
  const MANIFEST_FILENAME = 'mf-manifest.json';
12
- export { ASYNC_REQUIRE, DEFAULT_ENTRY_FILENAME, GET_DEV_SERVER_REGEX, HMR_CLIENT_REGEX, INIT_HOST, MANIFEST_FILENAME, REMOTE_HMR_SETUP, REMOTE_MODULE_REGISTRY, TMP_DIR_NAME };
13
+ export { ASYNC_REQUIRE, DEFAULT_ENTRY_FILENAME, GET_DEV_SERVER_REGEX, HMR_CLIENT_REGEX, INIT_HOST, MANIFEST_FILENAME, PLUGIN_IDENTIFIER, REMOTE_HMR_SETUP, REMOTE_MODULE_REGISTRY, TMP_DIR_NAME };
@@ -115,14 +115,20 @@ function generateShared(config) {
115
115
  return {
116
116
  id: sharedName,
117
117
  name: sharedName,
118
- version: config.shared[sharedName].version,
119
- requiredVersion: config.shared[sharedName].requiredVersion,
118
+ version: getManifestVersion(config.shared[sharedName].version),
119
+ requiredVersion: getManifestRequiredVersion(config.shared[sharedName].requiredVersion),
120
120
  singleton: config.shared[sharedName].singleton,
121
121
  hash: '',
122
122
  assets
123
123
  };
124
124
  });
125
125
  }
126
+ function getManifestVersion(version) {
127
+ return 'string' == typeof version ? version : '';
128
+ }
129
+ function getManifestRequiredVersion(requiredVersion) {
130
+ return 'string' == typeof requiredVersion ? requiredVersion : '*';
131
+ }
126
132
  function getEmptyAssets() {
127
133
  return {
128
134
  js: {
@@ -77,14 +77,20 @@ function generateShared(config) {
77
77
  return {
78
78
  id: sharedName,
79
79
  name: sharedName,
80
- version: config.shared[sharedName].version,
81
- requiredVersion: config.shared[sharedName].requiredVersion,
80
+ version: getManifestVersion(config.shared[sharedName].version),
81
+ requiredVersion: getManifestRequiredVersion(config.shared[sharedName].requiredVersion),
82
82
  singleton: config.shared[sharedName].singleton,
83
83
  hash: '',
84
84
  assets
85
85
  };
86
86
  });
87
87
  }
88
+ function getManifestVersion(version) {
89
+ return 'string' == typeof version ? version : '';
90
+ }
91
+ function getManifestRequiredVersion(requiredVersion) {
92
+ return 'string' == typeof requiredVersion ? requiredVersion : '*';
93
+ }
88
94
  function getEmptyAssets() {
89
95
  return {
90
96
  js: {
@@ -42,21 +42,41 @@ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_no
42
42
  const external_constants_js_namespaceObject = require("./constants.js");
43
43
  function normalizeOptions(options, { projectRoot, tmpDirPath }) {
44
44
  const shared = getNormalizedShared(options, projectRoot);
45
+ const remotes = getNormalizedRemotes(options);
46
+ const exposes = getNormalizedExposes(options);
45
47
  const shareStrategy = getNormalizedShareStrategy(options);
46
48
  const plugins = getNormalizedPlugins(options, tmpDirPath);
47
49
  return {
48
50
  name: options.name,
49
51
  filename: options.filename ?? external_constants_js_namespaceObject.DEFAULT_ENTRY_FILENAME,
50
- remotes: options.remotes ?? {},
51
- exposes: options.exposes ?? {},
52
+ remotes,
53
+ exposes,
52
54
  shared,
53
55
  shareStrategy,
54
56
  plugins
55
57
  };
56
58
  }
59
+ function getNormalizedRemotes(options) {
60
+ return {
61
+ ...options.remotes ?? {}
62
+ };
63
+ }
64
+ function getNormalizedExposes(options) {
65
+ return {
66
+ ...options.exposes ?? {}
67
+ };
68
+ }
57
69
  function getNormalizedShared(options, projectRoot) {
58
70
  const pkg = getProjectPackageJson(projectRoot);
59
- const shared = options.shared ?? {};
71
+ const sharedInput = options.shared ?? {};
72
+ const shared = Object.entries(sharedInput).reduce((acc, [sharedName, config])=>{
73
+ if ('string' == typeof config) return acc;
74
+ const metroSharedConfig = {
75
+ ...config
76
+ };
77
+ acc[sharedName] = metroSharedConfig;
78
+ return acc;
79
+ }, {});
60
80
  if (!options.exposes) for (const sharedName of Object.keys(shared))shared[sharedName].eager = true;
61
81
  for (const sharedName of Object.keys(shared))if (!shared[sharedName].requiredVersion) {
62
82
  var _pkg_dependencies, _pkg_devDependencies;
@@ -72,9 +92,27 @@ function getNormalizedShareStrategy(options) {
72
92
  return options.shareStrategy ?? 'loaded-first';
73
93
  }
74
94
  function getNormalizedPlugins(options, tmpDirPath) {
95
+ const runtimePlugins = getNormalizedRuntimePlugins(options);
75
96
  const plugins = options.plugins ?? [];
76
- plugins.unshift(require.resolve('../modules/metroCorePlugin.ts'));
77
- return plugins.map((pluginPath)=>external_node_path_default().relative(tmpDirPath, pluginPath));
97
+ const allPlugins = [
98
+ require.resolve('../modules/metroCorePlugin.ts'),
99
+ ...runtimePlugins,
100
+ ...plugins
101
+ ];
102
+ const deduplicatedPlugins = Array.from(new Set(allPlugins));
103
+ return deduplicatedPlugins.map((pluginPath)=>external_node_path_default().relative(tmpDirPath, pluginPath));
104
+ }
105
+ function getNormalizedRuntimePlugins(options) {
106
+ const runtimePlugins = options.runtimePlugins ?? [];
107
+ const normalizedRuntimePlugins = [];
108
+ runtimePlugins.forEach((runtimePlugin)=>{
109
+ if ('string' == typeof runtimePlugin) return void normalizedRuntimePlugins.push(runtimePlugin);
110
+ if (Array.isArray(runtimePlugin)) {
111
+ const [pluginPath] = runtimePlugin;
112
+ if ('string' == typeof pluginPath) normalizedRuntimePlugins.push(pluginPath);
113
+ }
114
+ });
115
+ return normalizedRuntimePlugins;
78
116
  }
79
117
  function getProjectPackageJson(projectRoot) {
80
118
  const packageJsonPath = external_node_path_default().join(projectRoot, 'package.json');
@@ -5,21 +5,41 @@ import node_path from "node:path";
5
5
  import { DEFAULT_ENTRY_FILENAME } from "./constants.mjs";
6
6
  function normalizeOptions(options, { projectRoot, tmpDirPath }) {
7
7
  const shared = getNormalizedShared(options, projectRoot);
8
+ const remotes = getNormalizedRemotes(options);
9
+ const exposes = getNormalizedExposes(options);
8
10
  const shareStrategy = getNormalizedShareStrategy(options);
9
11
  const plugins = getNormalizedPlugins(options, tmpDirPath);
10
12
  return {
11
13
  name: options.name,
12
14
  filename: options.filename ?? DEFAULT_ENTRY_FILENAME,
13
- remotes: options.remotes ?? {},
14
- exposes: options.exposes ?? {},
15
+ remotes,
16
+ exposes,
15
17
  shared,
16
18
  shareStrategy,
17
19
  plugins
18
20
  };
19
21
  }
22
+ function getNormalizedRemotes(options) {
23
+ return {
24
+ ...options.remotes ?? {}
25
+ };
26
+ }
27
+ function getNormalizedExposes(options) {
28
+ return {
29
+ ...options.exposes ?? {}
30
+ };
31
+ }
20
32
  function getNormalizedShared(options, projectRoot) {
21
33
  const pkg = getProjectPackageJson(projectRoot);
22
- const shared = options.shared ?? {};
34
+ const sharedInput = options.shared ?? {};
35
+ const shared = Object.entries(sharedInput).reduce((acc, [sharedName, config])=>{
36
+ if ('string' == typeof config) return acc;
37
+ const metroSharedConfig = {
38
+ ...config
39
+ };
40
+ acc[sharedName] = metroSharedConfig;
41
+ return acc;
42
+ }, {});
23
43
  if (!options.exposes) for (const sharedName of Object.keys(shared))shared[sharedName].eager = true;
24
44
  for (const sharedName of Object.keys(shared))if (!shared[sharedName].requiredVersion) {
25
45
  var _pkg_dependencies, _pkg_devDependencies;
@@ -35,9 +55,27 @@ function getNormalizedShareStrategy(options) {
35
55
  return options.shareStrategy ?? 'loaded-first';
36
56
  }
37
57
  function getNormalizedPlugins(options, tmpDirPath) {
58
+ const runtimePlugins = getNormalizedRuntimePlugins(options);
38
59
  const plugins = options.plugins ?? [];
39
- plugins.unshift(require.resolve('../modules/metroCorePlugin.ts'));
40
- return plugins.map((pluginPath)=>node_path.relative(tmpDirPath, pluginPath));
60
+ const allPlugins = [
61
+ require.resolve('../modules/metroCorePlugin.ts'),
62
+ ...runtimePlugins,
63
+ ...plugins
64
+ ];
65
+ const deduplicatedPlugins = Array.from(new Set(allPlugins));
66
+ return deduplicatedPlugins.map((pluginPath)=>node_path.relative(tmpDirPath, pluginPath));
67
+ }
68
+ function getNormalizedRuntimePlugins(options) {
69
+ const runtimePlugins = options.runtimePlugins ?? [];
70
+ const normalizedRuntimePlugins = [];
71
+ runtimePlugins.forEach((runtimePlugin)=>{
72
+ if ('string' == typeof runtimePlugin) return void normalizedRuntimePlugins.push(runtimePlugin);
73
+ if (Array.isArray(runtimePlugin)) {
74
+ const [pluginPath] = runtimePlugin;
75
+ if ('string' == typeof pluginPath) normalizedRuntimePlugins.push(pluginPath);
76
+ }
77
+ });
78
+ return normalizedRuntimePlugins;
41
79
  }
42
80
  function getProjectPackageJson(projectRoot) {
43
81
  const packageJsonPath = node_path.join(projectRoot, 'package.json');
@@ -37,13 +37,8 @@ __webpack_require__.d(__webpack_exports__, {
37
37
  });
38
38
  const external_node_path_namespaceObject = require("node:path");
39
39
  var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
40
- const baseJSBundle_namespaceObject = require("metro/src/DeltaBundler/Serializers/baseJSBundle");
41
- var baseJSBundle_default = /*#__PURE__*/ __webpack_require__.n(baseJSBundle_namespaceObject);
42
- const CountingSet_namespaceObject = require("metro/src/lib/CountingSet");
43
- var CountingSet_default = /*#__PURE__*/ __webpack_require__.n(CountingSet_namespaceObject);
44
- const bundleToString_namespaceObject = require("metro/src/lib/bundleToString");
45
- var bundleToString_default = /*#__PURE__*/ __webpack_require__.n(bundleToString_namespaceObject);
46
40
  const errors_js_namespaceObject = require("../utils/errors.js");
41
+ const metro_compat_js_namespaceObject = require("../utils/metro-compat.js");
47
42
  function getModuleFederationSerializer(mfConfig, isUsingMFBundleCommand) {
48
43
  return async (entryPoint, preModules, graph, options)=>{
49
44
  const syncRemoteModules = collectSyncRemoteModules(graph, mfConfig.remotes);
@@ -122,7 +117,7 @@ function generateVirtualModule(name, code) {
122
117
  return {
123
118
  dependencies: new Map(),
124
119
  getSource: ()=>Buffer.from(code),
125
- inverseDependencies: new (CountingSet_default())(),
120
+ inverseDependencies: new metro_compat_js_namespaceObject.CountingSet(),
126
121
  path: name,
127
122
  output: [
128
123
  {
@@ -159,7 +154,7 @@ function getBundlePath(entryPoint, projectRoot, exposes, isUsingMFBundleCommand)
159
154
  throw new errors_js_namespaceObject.ConfigError(`Unable to handle entry point: ${relativeEntryPath}. Expected to match an entrypoint with one of the exposed keys, but failed. This is most likely a configuration error. If you believe this is not a configuration issue, please report it as a bug. Debug info: entryPoint="${entryPoint}", projectRoot="${projectRoot}", exposesKeys=[${Object.keys(exposes).join(', ')}]`);
160
155
  }
161
156
  function getBundleCode(entryPoint, preModules, graph, options) {
162
- const { code } = bundleToString_default()(baseJSBundle_default()(entryPoint, preModules, graph, options));
157
+ const { code } = (0, metro_compat_js_namespaceObject.bundleToString)((0, metro_compat_js_namespaceObject.baseJSBundle)(entryPoint, preModules, graph, options));
163
158
  return code;
164
159
  }
165
160
  exports.getModuleFederationSerializer = __webpack_exports__.getModuleFederationSerializer;
@@ -2,34 +2,7 @@ import 'module';
2
2
  /*#__PURE__*/ import.meta.url;
3
3
  import node_path from "node:path";
4
4
  import { ConfigError } from "../utils/errors.mjs";
5
- import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "node:module";
6
- var __webpack_require__ = {};
7
- (()=>{
8
- __webpack_require__.n = (module)=>{
9
- var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
10
- __webpack_require__.d(getter, {
11
- a: getter
12
- });
13
- return getter;
14
- };
15
- })();
16
- (()=>{
17
- __webpack_require__.d = (exports, definition)=>{
18
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
19
- enumerable: true,
20
- get: definition[key]
21
- });
22
- };
23
- })();
24
- (()=>{
25
- __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
26
- })();
27
- const baseJSBundle_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("metro/src/DeltaBundler/Serializers/baseJSBundle");
28
- var baseJSBundle_default = /*#__PURE__*/ __webpack_require__.n(baseJSBundle_namespaceObject);
29
- const CountingSet_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("metro/src/lib/CountingSet");
30
- var CountingSet_default = /*#__PURE__*/ __webpack_require__.n(CountingSet_namespaceObject);
31
- const bundleToString_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("metro/src/lib/bundleToString");
32
- var bundleToString_default = /*#__PURE__*/ __webpack_require__.n(bundleToString_namespaceObject);
5
+ import { CountingSet, baseJSBundle, bundleToString } from "../utils/metro-compat.mjs";
33
6
  function getModuleFederationSerializer(mfConfig, isUsingMFBundleCommand) {
34
7
  return async (entryPoint, preModules, graph, options)=>{
35
8
  const syncRemoteModules = collectSyncRemoteModules(graph, mfConfig.remotes);
@@ -108,7 +81,7 @@ function generateVirtualModule(name, code) {
108
81
  return {
109
82
  dependencies: new Map(),
110
83
  getSource: ()=>Buffer.from(code),
111
- inverseDependencies: new (CountingSet_default())(),
84
+ inverseDependencies: new CountingSet(),
112
85
  path: name,
113
86
  output: [
114
87
  {
@@ -145,7 +118,7 @@ function getBundlePath(entryPoint, projectRoot, exposes, isUsingMFBundleCommand)
145
118
  throw new ConfigError(`Unable to handle entry point: ${relativeEntryPath}. Expected to match an entrypoint with one of the exposed keys, but failed. This is most likely a configuration error. If you believe this is not a configuration issue, please report it as a bug. Debug info: entryPoint="${entryPoint}", projectRoot="${projectRoot}", exposesKeys=[${Object.keys(exposes).join(', ')}]`);
146
119
  }
147
120
  function getBundleCode(entryPoint, preModules, graph, options) {
148
- const { code } = bundleToString_default()(baseJSBundle_default()(entryPoint, preModules, graph, options));
121
+ const { code } = bundleToString(baseJSBundle(entryPoint, preModules, graph, options));
149
122
  return code;
150
123
  }
151
124
  export { getModuleFederationSerializer };
@@ -1,5 +1,14 @@
1
1
  "use strict";
2
2
  var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
3
12
  (()=>{
4
13
  __webpack_require__.d = (exports1, definition)=>{
5
14
  for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
@@ -26,8 +35,40 @@ __webpack_require__.r(__webpack_exports__);
26
35
  __webpack_require__.d(__webpack_exports__, {
27
36
  validateOptions: ()=>validateOptions
28
37
  });
38
+ const external_logger_js_namespaceObject = require("../logger.js");
39
+ var external_logger_js_default = /*#__PURE__*/ __webpack_require__.n(external_logger_js_namespaceObject);
29
40
  const index_js_namespaceObject = require("../utils/index.js");
41
+ const unsupportedTopLevelOptions = [
42
+ 'library',
43
+ 'remoteType',
44
+ 'runtime',
45
+ 'shareScope',
46
+ 'getPublicPath',
47
+ 'implementation',
48
+ 'manifest',
49
+ 'dev',
50
+ 'dts',
51
+ 'dataPrefetch',
52
+ 'virtualRuntimeEntry',
53
+ 'experiments',
54
+ 'bridge',
55
+ 'async',
56
+ 'treeShakingDir',
57
+ 'injectTreeShakingUsedExports',
58
+ 'treeShakingSharedExcludePlugins',
59
+ 'treeShakingSharedPlugins'
60
+ ];
61
+ const unsupportedSharedFields = [
62
+ 'packageName',
63
+ 'shareKey',
64
+ 'shareScope',
65
+ 'strictVersion',
66
+ 'treeShaking',
67
+ 'shareStrategy'
68
+ ];
69
+ const warningSet = new Set();
30
70
  function validateName(name) {
71
+ if (!name || 'string' != typeof name) throw new index_js_namespaceObject.ConfigError("Option 'name' is required.");
31
72
  const validEcmaIdentifierRegex = /^[$_\p{ID_Start}][$_\u{200C}\u{200D}\p{ID_Continue}]*$/u;
32
73
  if (!validEcmaIdentifierRegex.test(name)) throw new index_js_namespaceObject.ConfigError(`Invalid 'name': ${name}. The 'name' must be a valid JavaScript identifier.`);
33
74
  }
@@ -39,17 +80,65 @@ function validateShared(shared) {
39
80
  if (!shared) throw new index_js_namespaceObject.ConfigError('Shared configuration is required.');
40
81
  if ('object' != typeof shared) throw new index_js_namespaceObject.ConfigError('Shared must be an object.');
41
82
  if (Array.isArray(shared)) throw new index_js_namespaceObject.ConfigError('Array format is not supported for shared.');
42
- if (!('react' in shared)) throw new index_js_namespaceObject.ConfigError("Dependency 'react' must be present in shared.");
43
- if (!('react-native' in shared)) throw new index_js_namespaceObject.ConfigError("Dependency 'react-native' must be present in shared.");
44
- for (const sharedName of Object.keys(shared)){
83
+ if (!isPlainObject(shared)) throw new index_js_namespaceObject.ConfigError('Shared must be an object.');
84
+ const sharedObject = shared;
85
+ if (!('react' in sharedObject)) throw new index_js_namespaceObject.ConfigError("Dependency 'react' must be present in shared.");
86
+ if (!('react-native' in sharedObject)) throw new index_js_namespaceObject.ConfigError("Dependency 'react-native' must be present in shared.");
87
+ for (const sharedName of Object.keys(sharedObject)){
88
+ const sharedConfig = sharedObject[sharedName];
45
89
  if (sharedName.startsWith('./') || sharedName.startsWith('../')) throw new index_js_namespaceObject.ConfigError('Relative paths are not supported as shared module names.');
46
90
  if (sharedName.startsWith('/')) throw new index_js_namespaceObject.ConfigError('Absolute paths are not supported as shared module names.');
47
91
  if (sharedName.endsWith('/')) throw new index_js_namespaceObject.ConfigError("Deep import wildcards are not supported as shared module names. You need to list all deep imports explicitly.");
92
+ if (!isPlainObject(sharedConfig)) throw new index_js_namespaceObject.ConfigError(`Unsupported shared format for '${sharedName}'. Metro only supports object notation for shared modules.`);
93
+ if ('import' in sharedConfig && false !== sharedConfig.import && 'string' != typeof sharedConfig.import) throw new index_js_namespaceObject.ConfigError(`Unsupported shared.import value for '${sharedName}'. Only string and false are supported in Metro.`);
94
+ for (const unsupportedField of unsupportedSharedFields)if (unsupportedField in sharedConfig) warnUnsupported(`shared.${sharedName}.${unsupportedField}`, `Option 'shared.${sharedName}.${unsupportedField}' is not supported in Metro and will have no effect.`);
48
95
  }
49
96
  }
97
+ function validateRemotes(remotes) {
98
+ if (void 0 === remotes) return;
99
+ if (!isPlainObject(remotes)) throw new index_js_namespaceObject.ConfigError('Unsupported remotes format. Metro only supports remotes as Record<string, string>.');
100
+ for (const remoteConfig of Object.values(remotes))if ('string' != typeof remoteConfig) throw new index_js_namespaceObject.ConfigError('Unsupported remotes format. Metro only supports remotes as Record<string, string>.');
101
+ }
102
+ function validateExposes(exposes) {
103
+ if (void 0 === exposes) return;
104
+ if (!isPlainObject(exposes)) throw new index_js_namespaceObject.ConfigError('Unsupported exposes format. Metro only supports exposes as Record<string, string>.');
105
+ for (const exposeConfig of Object.values(exposes))if ('string' != typeof exposeConfig) throw new index_js_namespaceObject.ConfigError('Unsupported exposes format. Metro only supports exposes as Record<string, string>.');
106
+ }
107
+ function validateRuntimePlugins(runtimePlugins) {
108
+ if (void 0 === runtimePlugins) return;
109
+ if (!Array.isArray(runtimePlugins)) throw new index_js_namespaceObject.ConfigError('runtimePlugins must be an array.');
110
+ runtimePlugins.forEach((runtimePlugin, index)=>{
111
+ if ('string' == typeof runtimePlugin) return;
112
+ if (!Array.isArray(runtimePlugin)) throw new index_js_namespaceObject.ConfigError('runtimePlugins entries must be either a string or a tuple of [path, params].');
113
+ const [pluginPath, pluginParams] = runtimePlugin;
114
+ if ('string' != typeof pluginPath) throw new index_js_namespaceObject.ConfigError(`Invalid runtimePlugins[${index}] path. Expected a string path.`);
115
+ if (void 0 !== pluginParams) warnUnsupported(`runtimePlugins[${index}][1]`, `Option 'runtimePlugins[${index}][1]' is not supported in Metro and will have no effect.`);
116
+ });
117
+ }
118
+ function validateUnsupportedTopLevelOptions(options) {
119
+ unsupportedTopLevelOptions.forEach((unsupportedOption)=>{
120
+ if (void 0 !== options[unsupportedOption]) warnUnsupported(String(unsupportedOption), `Option '${String(unsupportedOption)}' is not supported in Metro and will have no effect.`);
121
+ });
122
+ }
123
+ function validateDeprecatedOptions(options) {
124
+ if (options.plugins && options.plugins.length > 0) warnUnsupported('deprecated.plugins', "The 'plugins' option is deprecated. Use 'runtimePlugins' instead. Support for 'plugins' will be removed in the next major version.");
125
+ }
126
+ function warnUnsupported(key, message) {
127
+ if (warningSet.has(key)) return;
128
+ warningSet.add(key);
129
+ external_logger_js_default().warn(message);
130
+ }
131
+ function isPlainObject(value) {
132
+ return 'object' == typeof value && null !== value && !Array.isArray(value);
133
+ }
50
134
  function validateOptions(options) {
135
+ validateUnsupportedTopLevelOptions(options);
136
+ validateDeprecatedOptions(options);
51
137
  validateName(options.name);
52
138
  validateFilename(options.filename);
139
+ validateRemotes(options.remotes);
140
+ validateExposes(options.exposes);
141
+ validateRuntimePlugins(options.runtimePlugins);
53
142
  validateShared(options.shared);
54
143
  }
55
144
  exports.validateOptions = __webpack_exports__.validateOptions;
@@ -1,7 +1,38 @@
1
1
  import 'module';
2
2
  /*#__PURE__*/ import.meta.url;
3
+ import logger from "../logger.mjs";
3
4
  import { ConfigError } from "../utils/index.mjs";
5
+ const unsupportedTopLevelOptions = [
6
+ 'library',
7
+ 'remoteType',
8
+ 'runtime',
9
+ 'shareScope',
10
+ 'getPublicPath',
11
+ 'implementation',
12
+ 'manifest',
13
+ 'dev',
14
+ 'dts',
15
+ 'dataPrefetch',
16
+ 'virtualRuntimeEntry',
17
+ 'experiments',
18
+ 'bridge',
19
+ 'async',
20
+ 'treeShakingDir',
21
+ 'injectTreeShakingUsedExports',
22
+ 'treeShakingSharedExcludePlugins',
23
+ 'treeShakingSharedPlugins'
24
+ ];
25
+ const unsupportedSharedFields = [
26
+ 'packageName',
27
+ 'shareKey',
28
+ 'shareScope',
29
+ 'strictVersion',
30
+ 'treeShaking',
31
+ 'shareStrategy'
32
+ ];
33
+ const warningSet = new Set();
4
34
  function validateName(name) {
35
+ if (!name || 'string' != typeof name) throw new ConfigError("Option 'name' is required.");
5
36
  const validEcmaIdentifierRegex = /^[$_\p{ID_Start}][$_\u{200C}\u{200D}\p{ID_Continue}]*$/u;
6
37
  if (!validEcmaIdentifierRegex.test(name)) throw new ConfigError(`Invalid 'name': ${name}. The 'name' must be a valid JavaScript identifier.`);
7
38
  }
@@ -13,17 +44,65 @@ function validateShared(shared) {
13
44
  if (!shared) throw new ConfigError('Shared configuration is required.');
14
45
  if ('object' != typeof shared) throw new ConfigError('Shared must be an object.');
15
46
  if (Array.isArray(shared)) throw new ConfigError('Array format is not supported for shared.');
16
- if (!('react' in shared)) throw new ConfigError("Dependency 'react' must be present in shared.");
17
- if (!('react-native' in shared)) throw new ConfigError("Dependency 'react-native' must be present in shared.");
18
- for (const sharedName of Object.keys(shared)){
47
+ if (!isPlainObject(shared)) throw new ConfigError('Shared must be an object.');
48
+ const sharedObject = shared;
49
+ if (!('react' in sharedObject)) throw new ConfigError("Dependency 'react' must be present in shared.");
50
+ if (!('react-native' in sharedObject)) throw new ConfigError("Dependency 'react-native' must be present in shared.");
51
+ for (const sharedName of Object.keys(sharedObject)){
52
+ const sharedConfig = sharedObject[sharedName];
19
53
  if (sharedName.startsWith('./') || sharedName.startsWith('../')) throw new ConfigError('Relative paths are not supported as shared module names.');
20
54
  if (sharedName.startsWith('/')) throw new ConfigError('Absolute paths are not supported as shared module names.');
21
55
  if (sharedName.endsWith('/')) throw new ConfigError("Deep import wildcards are not supported as shared module names. You need to list all deep imports explicitly.");
56
+ if (!isPlainObject(sharedConfig)) throw new ConfigError(`Unsupported shared format for '${sharedName}'. Metro only supports object notation for shared modules.`);
57
+ if ('import' in sharedConfig && false !== sharedConfig.import && 'string' != typeof sharedConfig.import) throw new ConfigError(`Unsupported shared.import value for '${sharedName}'. Only string and false are supported in Metro.`);
58
+ for (const unsupportedField of unsupportedSharedFields)if (unsupportedField in sharedConfig) warnUnsupported(`shared.${sharedName}.${unsupportedField}`, `Option 'shared.${sharedName}.${unsupportedField}' is not supported in Metro and will have no effect.`);
22
59
  }
23
60
  }
61
+ function validateRemotes(remotes) {
62
+ if (void 0 === remotes) return;
63
+ if (!isPlainObject(remotes)) throw new ConfigError('Unsupported remotes format. Metro only supports remotes as Record<string, string>.');
64
+ for (const remoteConfig of Object.values(remotes))if ('string' != typeof remoteConfig) throw new ConfigError('Unsupported remotes format. Metro only supports remotes as Record<string, string>.');
65
+ }
66
+ function validateExposes(exposes) {
67
+ if (void 0 === exposes) return;
68
+ if (!isPlainObject(exposes)) throw new ConfigError('Unsupported exposes format. Metro only supports exposes as Record<string, string>.');
69
+ for (const exposeConfig of Object.values(exposes))if ('string' != typeof exposeConfig) throw new ConfigError('Unsupported exposes format. Metro only supports exposes as Record<string, string>.');
70
+ }
71
+ function validateRuntimePlugins(runtimePlugins) {
72
+ if (void 0 === runtimePlugins) return;
73
+ if (!Array.isArray(runtimePlugins)) throw new ConfigError('runtimePlugins must be an array.');
74
+ runtimePlugins.forEach((runtimePlugin, index)=>{
75
+ if ('string' == typeof runtimePlugin) return;
76
+ if (!Array.isArray(runtimePlugin)) throw new ConfigError('runtimePlugins entries must be either a string or a tuple of [path, params].');
77
+ const [pluginPath, pluginParams] = runtimePlugin;
78
+ if ('string' != typeof pluginPath) throw new ConfigError(`Invalid runtimePlugins[${index}] path. Expected a string path.`);
79
+ if (void 0 !== pluginParams) warnUnsupported(`runtimePlugins[${index}][1]`, `Option 'runtimePlugins[${index}][1]' is not supported in Metro and will have no effect.`);
80
+ });
81
+ }
82
+ function validateUnsupportedTopLevelOptions(options) {
83
+ unsupportedTopLevelOptions.forEach((unsupportedOption)=>{
84
+ if (void 0 !== options[unsupportedOption]) warnUnsupported(String(unsupportedOption), `Option '${String(unsupportedOption)}' is not supported in Metro and will have no effect.`);
85
+ });
86
+ }
87
+ function validateDeprecatedOptions(options) {
88
+ if (options.plugins && options.plugins.length > 0) warnUnsupported('deprecated.plugins', "The 'plugins' option is deprecated. Use 'runtimePlugins' instead. Support for 'plugins' will be removed in the next major version.");
89
+ }
90
+ function warnUnsupported(key, message) {
91
+ if (warningSet.has(key)) return;
92
+ warningSet.add(key);
93
+ logger.warn(message);
94
+ }
95
+ function isPlainObject(value) {
96
+ return 'object' == typeof value && null !== value && !Array.isArray(value);
97
+ }
24
98
  function validateOptions(options) {
99
+ validateUnsupportedTopLevelOptions(options);
100
+ validateDeprecatedOptions(options);
25
101
  validateName(options.name);
26
102
  validateFilename(options.filename);
103
+ validateRemotes(options.remotes);
104
+ validateExposes(options.exposes);
105
+ validateRuntimePlugins(options.runtimePlugins);
27
106
  validateShared(options.shared);
28
107
  }
29
108
  export { validateOptions };
package/dist/types.d.ts CHANGED
@@ -1,21 +1,20 @@
1
- export interface SharedConfig {
2
- singleton: boolean;
3
- eager: boolean;
4
- version: string;
5
- requiredVersion: string;
6
- import?: false;
1
+ import type { moduleFederationPlugin } from '@module-federation/sdk';
2
+ export interface ModuleFederationConfig extends moduleFederationPlugin.ModuleFederationPluginOptions {
3
+ /**
4
+ * @deprecated Use runtimePlugins instead. Scheduled for removal in the next major version.
5
+ */
6
+ plugins?: string[];
7
7
  }
8
- export type Shared = Record<string, SharedConfig>;
9
- export interface ModuleFederationConfig {
8
+ export type ShareObject = Record<string, moduleFederationPlugin.SharedConfig>;
9
+ export interface ModuleFederationConfigNormalized {
10
10
  name: string;
11
- filename?: string;
12
- remotes?: Record<string, string>;
13
- exposes?: Record<string, string>;
14
- shared?: Shared;
15
- shareStrategy?: 'loaded-first' | 'version-first';
16
- plugins?: string[];
11
+ filename: string;
12
+ remotes: Record<string, string>;
13
+ exposes: Record<string, string>;
14
+ shared: ShareObject;
15
+ shareStrategy: moduleFederationPlugin.SharedStrategy;
16
+ plugins: string[];
17
17
  }
18
- export type ModuleFederationConfigNormalized = Required<ModuleFederationConfig>;
19
18
  export type ModuleFederationExtraOptions = {
20
19
  flags?: MetroMFFlags;
21
20
  };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Metro Compatibility Layer
3
+ *
4
+ * Provides backwards-compatible imports for Metro 0.82 and 0.83+
5
+ *
6
+ * Metro 0.83 introduced a restrictive `exports` field that only allows
7
+ * `metro/private/*` paths instead of direct `metro/src/*` imports.
8
+ *
9
+ * This module dynamically resolves the correct import path based on the
10
+ * installed Metro version, ensuring compatibility with both versions.
11
+ */
12
+ import type DefaultServer from 'metro/src/Server';
13
+ import type DefaultBaseJSBundle from 'metro/src/DeltaBundler/Serializers/baseJSBundle';
14
+ import type DefaultCountingSet from 'metro/src/lib/CountingSet';
15
+ import type DefaultBundleToString from 'metro/src/lib/bundleToString';
16
+ import type { MixedSourceMap } from 'metro-source-map';
17
+ export declare const Server: typeof DefaultServer;
18
+ export type Server = DefaultServer;
19
+ export declare const baseJSBundle: typeof DefaultBaseJSBundle;
20
+ export declare const CountingSet: typeof DefaultCountingSet;
21
+ export declare const bundleToString: typeof DefaultBundleToString;
22
+ export declare const relativizeSourceMapInline: (sourceMap: MixedSourceMap, sourcesRoot: string) => void;
23
+ export type { RequestOptions, OutputOptions } from 'metro/src/shared/types';
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ CountingSet: ()=>CountingSet,
28
+ Server: ()=>Server,
29
+ baseJSBundle: ()=>baseJSBundle,
30
+ bundleToString: ()=>bundleToString,
31
+ relativizeSourceMapInline: ()=>relativizeSourceMapInline
32
+ });
33
+ function resolveAndImport(metro83Path, metro82Path) {
34
+ let resolvedPath;
35
+ try {
36
+ resolvedPath = require.resolve(metro83Path);
37
+ } catch {
38
+ try {
39
+ resolvedPath = require.resolve(metro82Path);
40
+ } catch {
41
+ throw new Error(`Could not resolve 'metro' module. Tried:\n - ${metro83Path}\n - ${metro82Path}\nEnsure 'metro' is installed.`);
42
+ }
43
+ }
44
+ return require(resolvedPath);
45
+ }
46
+ function getDefaultExport(mod) {
47
+ if (null != mod && 'object' == typeof mod && 'default' in mod) return mod.default;
48
+ return mod;
49
+ }
50
+ const Server = getDefaultExport(resolveAndImport('metro/private/Server', 'metro/src/Server'));
51
+ const baseJSBundle = getDefaultExport(resolveAndImport('metro/private/DeltaBundler/Serializers/baseJSBundle', 'metro/src/DeltaBundler/Serializers/baseJSBundle'));
52
+ const CountingSet = getDefaultExport(resolveAndImport('metro/private/lib/CountingSet', 'metro/src/lib/CountingSet'));
53
+ const bundleToString = getDefaultExport(resolveAndImport('metro/private/lib/bundleToString', 'metro/src/lib/bundleToString'));
54
+ const relativizeSourceMapModule = resolveAndImport('metro/private/lib/relativizeSourceMap', 'metro/src/lib/relativizeSourceMap');
55
+ const relativizeSourceMapInline = relativizeSourceMapModule.relativizeSourceMapInline || getDefaultExport(relativizeSourceMapModule);
56
+ exports.CountingSet = __webpack_exports__.CountingSet;
57
+ exports.Server = __webpack_exports__.Server;
58
+ exports.baseJSBundle = __webpack_exports__.baseJSBundle;
59
+ exports.bundleToString = __webpack_exports__.bundleToString;
60
+ exports.relativizeSourceMapInline = __webpack_exports__.relativizeSourceMapInline;
61
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
62
+ "CountingSet",
63
+ "Server",
64
+ "baseJSBundle",
65
+ "bundleToString",
66
+ "relativizeSourceMapInline"
67
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
68
+ Object.defineProperty(exports, '__esModule', {
69
+ value: true
70
+ });
@@ -0,0 +1,26 @@
1
+ import __rslib_shim_module__ from 'module';
2
+ const require = /*#__PURE__*/ __rslib_shim_module__.createRequire(import.meta.url);
3
+ function resolveAndImport(metro83Path, metro82Path) {
4
+ let resolvedPath;
5
+ try {
6
+ resolvedPath = require.resolve(metro83Path);
7
+ } catch {
8
+ try {
9
+ resolvedPath = require.resolve(metro82Path);
10
+ } catch {
11
+ throw new Error(`Could not resolve 'metro' module. Tried:\n - ${metro83Path}\n - ${metro82Path}\nEnsure 'metro' is installed.`);
12
+ }
13
+ }
14
+ return require(resolvedPath);
15
+ }
16
+ function getDefaultExport(mod) {
17
+ if (null != mod && 'object' == typeof mod && 'default' in mod) return mod.default;
18
+ return mod;
19
+ }
20
+ const Server = getDefaultExport(resolveAndImport('metro/private/Server', 'metro/src/Server'));
21
+ const baseJSBundle = getDefaultExport(resolveAndImport('metro/private/DeltaBundler/Serializers/baseJSBundle', 'metro/src/DeltaBundler/Serializers/baseJSBundle'));
22
+ const CountingSet = getDefaultExport(resolveAndImport('metro/private/lib/CountingSet', 'metro/src/lib/CountingSet'));
23
+ const bundleToString = getDefaultExport(resolveAndImport('metro/private/lib/bundleToString', 'metro/src/lib/bundleToString'));
24
+ const relativizeSourceMapModule = resolveAndImport('metro/private/lib/relativizeSourceMap', 'metro/src/lib/relativizeSourceMap');
25
+ const relativizeSourceMapInline = relativizeSourceMapModule.relativizeSourceMapInline || getDefaultExport(relativizeSourceMapModule);
26
+ export { CountingSet, Server, baseJSBundle, bundleToString, relativizeSourceMapInline };
@@ -1,5 +1,5 @@
1
1
  import type { MetroConfig, ServerConfigT, TransformerConfigT } from 'metro-config';
2
- import type MetroServer from 'metro/src/Server';
2
+ import type { Server as MetroServer } from './metro-compat';
3
3
  type EnhanceMiddleware = ServerConfigT['enhanceMiddleware'];
4
4
  type GetTransformOptions = TransformerConfigT['getTransformOptions'];
5
5
  type Bundler = ReturnType<ReturnType<MetroServer['getBundler']>['getBundler']>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/metro",
3
- "version": "0.0.0-fix-loop-load-20260203135642",
3
+ "version": "0.0.0-fix-array-share-scope-20260225123251",
4
4
  "description": "Module Federation for Metro bundler",
5
5
  "keywords": [
6
6
  "module-federation",
@@ -57,8 +57,8 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "@expo/metro-runtime": "^5.0.4",
60
- "@module-federation/runtime": "0.0.0-fix-loop-load-20260203135642",
61
- "@module-federation/sdk": "0.0.0-fix-loop-load-20260203135642"
60
+ "@module-federation/runtime": "0.0.0-fix-array-share-scope-20260225123251",
61
+ "@module-federation/sdk": "0.0.0-fix-array-share-scope-20260225123251"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "@babel/types": "^7.25.0",
@@ -84,6 +84,7 @@
84
84
  "@typescript-eslint/parser": "8.54.0",
85
85
  "@types/node": "^20.19.5",
86
86
  "@types/react": "^19.1.0",
87
+ "memfs": "4.46.0",
87
88
  "metro": "^0.82.1",
88
89
  "metro-config": "^0.82.1",
89
90
  "metro-file-map": "^0.82.1",
@@ -96,6 +97,8 @@
96
97
  },
97
98
  "scripts": {
98
99
  "build": "rslib build",
100
+ "test": "vitest run --config vitest.config.mts",
101
+ "test:watch": "vitest --config vitest.config.mts",
99
102
  "typecheck": "tsc --noEmit"
100
103
  }
101
104
  }