@vercel/microfrontends 1.5.0-canary.2 → 2.0.0-canary.0

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 (59) hide show
  1. package/CHANGELOG.md +10 -18
  2. package/dist/bin/cli.cjs +103 -117
  3. package/dist/config.cjs +48 -101
  4. package/dist/config.cjs.map +1 -1
  5. package/dist/config.d.ts +2 -29
  6. package/dist/config.js +37 -100
  7. package/dist/config.js.map +1 -1
  8. package/dist/experimental/sveltekit.cjs +93 -109
  9. package/dist/experimental/sveltekit.cjs.map +1 -1
  10. package/dist/experimental/sveltekit.js +92 -108
  11. package/dist/experimental/sveltekit.js.map +1 -1
  12. package/dist/experimental/vite.cjs +93 -109
  13. package/dist/experimental/vite.cjs.map +1 -1
  14. package/dist/experimental/vite.js +92 -108
  15. package/dist/experimental/vite.js.map +1 -1
  16. package/dist/get-application-context-e8a5a0e2.d.ts +14 -0
  17. package/dist/microfrontends/server.cjs +93 -109
  18. package/dist/microfrontends/server.cjs.map +1 -1
  19. package/dist/microfrontends/server.d.ts +4 -13
  20. package/dist/microfrontends/server.js +92 -108
  21. package/dist/microfrontends/server.js.map +1 -1
  22. package/dist/microfrontends/utils.cjs +24 -4
  23. package/dist/microfrontends/utils.cjs.map +1 -1
  24. package/dist/microfrontends/utils.d.ts +3 -1
  25. package/dist/microfrontends/utils.js +24 -4
  26. package/dist/microfrontends/utils.js.map +1 -1
  27. package/dist/next/client.cjs +1 -1
  28. package/dist/next/client.cjs.map +1 -1
  29. package/dist/next/client.js +1 -1
  30. package/dist/next/client.js.map +1 -1
  31. package/dist/next/config.cjs +244 -117
  32. package/dist/next/config.cjs.map +1 -1
  33. package/dist/next/config.d.ts +1 -1
  34. package/dist/next/config.js +243 -116
  35. package/dist/next/config.js.map +1 -1
  36. package/dist/next/middleware.cjs +88 -44
  37. package/dist/next/middleware.cjs.map +1 -1
  38. package/dist/next/middleware.js +78 -44
  39. package/dist/next/middleware.js.map +1 -1
  40. package/dist/next/testing.cjs +51 -104
  41. package/dist/next/testing.cjs.map +1 -1
  42. package/dist/next/testing.d.ts +2 -2
  43. package/dist/next/testing.js +39 -102
  44. package/dist/next/testing.js.map +1 -1
  45. package/dist/overrides.d.ts +3 -3
  46. package/dist/schema.d.ts +2 -2
  47. package/dist/{types-1cec43e6.d.ts → types-0deb756b.d.ts} +16 -1
  48. package/dist/{types-1fb60496.d.ts → types-4299bff1.d.ts} +1 -1
  49. package/dist/utils/mfe-port.cjs +93 -109
  50. package/dist/utils/mfe-port.cjs.map +1 -1
  51. package/dist/utils/mfe-port.js +92 -108
  52. package/dist/utils/mfe-port.js.map +1 -1
  53. package/dist/validation.cjs +4 -0
  54. package/dist/validation.cjs.map +1 -1
  55. package/dist/validation.d.ts +1 -1
  56. package/dist/validation.js +4 -0
  57. package/dist/validation.js.map +1 -1
  58. package/package.json +3 -1
  59. package/schema/schema.json +4 -0
@@ -1,6 +1,6 @@
1
1
  import { NextConfig } from 'next';
2
2
 
3
- type TransformKeys = 'assetPrefix' | 'buildId' | 'draftMode' | 'redirects' | 'rewrites' | 'webpack';
3
+ type TransformKeys = 'assetPrefix' | 'buildId' | 'draftMode' | 'redirects' | 'rewrites' | 'transpilePackages' | 'webpack';
4
4
 
5
5
  interface WithMicrofrontendsOptions {
6
6
  /**
@@ -214,8 +214,9 @@ var CONFIGURATION_FILENAMES = [
214
214
  var configCache = {};
215
215
  function findPackageWithMicrofrontendsConfig({
216
216
  repositoryRoot,
217
- applicationName
217
+ applicationContext
218
218
  }) {
219
+ const applicationName = applicationContext.name;
219
220
  try {
220
221
  const microfrontendsJsonPaths = fg.globSync(
221
222
  `**/{${CONFIGURATION_FILENAMES.join(",")}}`,
@@ -257,26 +258,45 @@ ${matchingPaths.join("\n \u2022 ")}`,
257
258
  );
258
259
  }
259
260
  if (matchingPaths.length === 0) {
261
+ let additionalErrorMessage = "";
262
+ if (microfrontendsJsonPaths.length > 0) {
263
+ if (!applicationContext.projectName) {
264
+ additionalErrorMessage = `
265
+
266
+ If the name in package.json (${applicationContext.packageJsonName}) differs from your Vercel Project name, set the \`packageName\` field for the application in \`microfrontends.json\` to ensure that the configuration can be found locally.`;
267
+ } else {
268
+ additionalErrorMessage = `
269
+
270
+ Names of applications in \`microfrontends.json\` must match the Vercel Project name (${applicationContext.projectName}).`;
271
+ }
272
+ }
260
273
  throw new MicrofrontendError(
261
- `Could not find a \`microfrontends.json\` file in the repository that contains "applications.${applicationName}". If your Vercel Microfrontends configuration is not in this repository, you can use the Vercel CLI to pull the Vercel Microfrontends configuration using the "vercel microfrontends pull" command, or you can specify the path manually using the VC_MICROFRONTENDS_CONFIG environment variable. If you suspect this is thrown in error, please reach out to the Vercel team.`,
274
+ `Could not find a \`microfrontends.json\` file in the repository that contains the "${applicationName}" application.${additionalErrorMessage}
275
+
276
+ If your Vercel Microfrontends configuration is not in this repository, you can use the Vercel CLI to pull the Vercel Microfrontends configuration using the "vercel microfrontends pull" command, or you can specify the path manually using the VC_MICROFRONTENDS_CONFIG environment variable.
277
+
278
+ If you suspect this is thrown in error, please reach out to the Vercel team.`,
262
279
  { type: "config", subtype: "inference_failed" }
263
280
  );
264
281
  }
265
282
  const [packageJsonPath] = matchingPaths;
266
283
  return dirname(packageJsonPath);
267
284
  } catch (error) {
285
+ if (error instanceof MicrofrontendError) {
286
+ throw error;
287
+ }
268
288
  return null;
269
289
  }
270
290
  }
271
291
  function inferMicrofrontendsLocation(opts) {
272
- const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;
292
+ const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}`;
273
293
  if (configCache[cacheKey]) {
274
294
  return configCache[cacheKey];
275
295
  }
276
296
  const result = findPackageWithMicrofrontendsConfig(opts);
277
297
  if (!result) {
278
298
  throw new MicrofrontendError(
279
- `Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationName}" starting in directory "${opts.repositoryRoot}".`,
299
+ `Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationContext.name}" starting in directory "${opts.repositoryRoot}".`,
280
300
  { type: "config", subtype: "inference_failed" }
281
301
  );
282
302
  }
@@ -348,90 +368,13 @@ function findConfig({ dir }) {
348
368
  // src/config/microfrontends-config/isomorphic/index.ts
349
369
  import { parse as parse2 } from "jsonc-parser";
350
370
 
351
- // src/config/microfrontends-config/client/index.ts
352
- import { pathToRegexp } from "path-to-regexp";
353
- var regexpCache = /* @__PURE__ */ new Map();
354
- var getRegexp = (path6) => {
355
- const existing = regexpCache.get(path6);
356
- if (existing) {
357
- return existing;
358
- }
359
- const regexp = pathToRegexp(path6);
360
- regexpCache.set(path6, regexp);
361
- return regexp;
362
- };
363
- var MicrofrontendConfigClient = class {
364
- constructor(config, opts) {
365
- this.pathCache = {};
366
- this.serialized = config;
367
- if (opts?.removeFlaggedPaths) {
368
- for (const app of Object.values(config.applications)) {
369
- if (app.routing) {
370
- app.routing = app.routing.filter((match) => !match.flag);
371
- }
372
- }
373
- }
374
- this.applications = config.applications;
375
- }
376
- /**
377
- * Create a new `MicrofrontendConfigClient` from a JSON string.
378
- * Config must be passed in to remain framework agnostic
379
- */
380
- static fromEnv(config, opts) {
381
- if (!config) {
382
- throw new Error(
383
- "Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
384
- );
385
- }
386
- return new MicrofrontendConfigClient(
387
- JSON.parse(config),
388
- opts
389
- );
390
- }
391
- isEqual(other) {
392
- return this === other || JSON.stringify(this.applications) === JSON.stringify(other.applications);
393
- }
394
- getApplicationNameForPath(path6) {
395
- if (!path6.startsWith("/")) {
396
- throw new Error(`Path must start with a /`);
397
- }
398
- if (this.pathCache[path6]) {
399
- return this.pathCache[path6];
400
- }
401
- const pathname = new URL(path6, "https://example.com").pathname;
402
- for (const [name, application] of Object.entries(this.applications)) {
403
- if (application.routing) {
404
- for (const group of application.routing) {
405
- for (const childPath of group.paths) {
406
- const regexp = getRegexp(childPath);
407
- if (regexp.test(pathname)) {
408
- this.pathCache[path6] = name;
409
- return name;
410
- }
411
- }
412
- }
413
- }
414
- }
415
- const defaultApplication = Object.entries(this.applications).find(
416
- ([, application]) => application.default
417
- );
418
- if (!defaultApplication) {
419
- return null;
420
- }
421
- this.pathCache[path6] = defaultApplication[0];
422
- return defaultApplication[0];
423
- }
424
- serialize() {
425
- return this.serialized;
426
- }
427
- };
428
-
429
371
  // src/config/microfrontends-config/isomorphic/validation.ts
430
- import { pathToRegexp as pathToRegexp2, parse as parsePathRegexp } from "path-to-regexp";
372
+ import { pathToRegexp, parse as parsePathRegexp } from "path-to-regexp";
431
373
  var LIST_FORMATTER = new Intl.ListFormat("en", {
432
374
  style: "long",
433
375
  type: "conjunction"
434
376
  });
377
+ var VALID_ASSET_PREFIX_REGEXP = /^[a-z](?:[a-z0-9-]*[a-z0-9])?$/;
435
378
  var validateConfigPaths = (applicationConfigsById) => {
436
379
  if (!applicationConfigsById) {
437
380
  return;
@@ -454,7 +397,7 @@ var validateConfigPaths = (applicationConfigsById) => {
454
397
  } else {
455
398
  pathsByApplicationId.set(path6, {
456
399
  applications: [id],
457
- matcher: pathToRegexp2(path6),
400
+ matcher: pathToRegexp(path6),
458
401
  applicationId: id
459
402
  });
460
403
  }
@@ -558,6 +501,22 @@ var validateAppPaths = (name, app) => {
558
501
  }
559
502
  }
560
503
  }
504
+ if (app.assetPrefix) {
505
+ if (!VALID_ASSET_PREFIX_REGEXP.test(app.assetPrefix)) {
506
+ throw new MicrofrontendError(
507
+ `Invalid asset prefix for application "${name}". ${app.assetPrefix} must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`,
508
+ { type: "application", subtype: "invalid_asset_prefix" }
509
+ );
510
+ }
511
+ if (app.assetPrefix !== `vc-ap-${name}` && !app.routing.some(
512
+ (group) => group.paths.includes(`/${app.assetPrefix}/:path*`) && !group.flag
513
+ )) {
514
+ throw new MicrofrontendError(
515
+ `When \`assetPrefix\` is specified, \`/${app.assetPrefix}/:path*\` must be added the routing paths for the application. Changing the asset prefix is not a forwards and backwards compatible change, and the custom asset prefix should be added to \`paths\` and deployed before setting the \`assetPrefix\` field.`,
516
+ { type: "application", subtype: "invalid_asset_prefix" }
517
+ );
518
+ }
519
+ }
561
520
  };
562
521
  var validateConfigDefaultApplication = (applicationConfigsById) => {
563
522
  if (!applicationConfigsById) {
@@ -589,6 +548,15 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
589
548
  }
590
549
  };
591
550
 
551
+ // src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts
552
+ import md5 from "md5";
553
+ function hashApplicationName(name) {
554
+ if (!name) {
555
+ throw new Error("Application name is required to generate hash");
556
+ }
557
+ return md5(name).substring(0, 6).padStart(6, "0");
558
+ }
559
+
592
560
  // src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
593
561
  var PREFIX = "vc-ap";
594
562
  function generateAssetPrefixFromName({
@@ -597,7 +565,7 @@ function generateAssetPrefixFromName({
597
565
  if (!name) {
598
566
  throw new Error("Name is required to generate an asset prefix");
599
567
  }
600
- return `${PREFIX}-${name}`;
568
+ return `${PREFIX}-${hashApplicationName(name)}`;
601
569
  }
602
570
 
603
571
  // src/config/microfrontends-config/isomorphic/utils/generate-port.ts
@@ -757,7 +725,13 @@ var Application = class {
757
725
  return this.default;
758
726
  }
759
727
  getAssetPrefix() {
760
- return generateAssetPrefixFromName({ name: this.name });
728
+ const generatedAssetPrefix = generateAssetPrefixFromName({
729
+ name: this.name
730
+ });
731
+ if ("assetPrefix" in this.serialized) {
732
+ return this.serialized.assetPrefix ?? generatedAssetPrefix;
733
+ }
734
+ return generatedAssetPrefix;
761
735
  }
762
736
  getAutomationBypassEnvVarName() {
763
737
  return generateAutomationBypassEnvVarName({ name: this.name });
@@ -891,7 +865,7 @@ var MicrofrontendConfigIsomorphic = class {
891
865
  );
892
866
  if (!app) {
893
867
  throw new MicrofrontendError(
894
- `Could not find microfrontends configuration for application "${name}"`,
868
+ `Could not find microfrontends configuration for application "${name}". If the name in package.json differs from your Vercel Project name, set the \`packageName\` field for the application in \`microfrontends.json\` to ensure that the configuration can be found locally.`,
895
869
  {
896
870
  type: "application",
897
871
  subtype: "not_found"
@@ -936,23 +910,6 @@ var MicrofrontendConfigIsomorphic = class {
936
910
  toSchemaJson() {
937
911
  return this.serialized.config;
938
912
  }
939
- toClientConfig() {
940
- const applications = Object.fromEntries(
941
- Object.entries(this.childApplications).map(([name, application]) => [
942
- name,
943
- {
944
- default: false,
945
- routing: application.routing
946
- }
947
- ])
948
- );
949
- applications[this.defaultApplication.name] = {
950
- default: true
951
- };
952
- return new MicrofrontendConfigClient({
953
- applications
954
- });
955
- }
956
913
  serialize() {
957
914
  return this.serialized;
958
915
  }
@@ -965,8 +922,31 @@ function getApplicationContext(opts) {
965
922
  if (opts?.appName) {
966
923
  return { name: opts.appName };
967
924
  }
925
+ if (process.env.VERCEL_PROJECT_NAME) {
926
+ return {
927
+ name: process.env.VERCEL_PROJECT_NAME,
928
+ projectName: process.env.VERCEL_PROJECT_NAME
929
+ };
930
+ }
968
931
  if (process.env.NX_TASK_TARGET_PROJECT) {
969
- return { name: process.env.NX_TASK_TARGET_PROJECT };
932
+ return {
933
+ name: process.env.NX_TASK_TARGET_PROJECT,
934
+ packageJsonName: process.env.NX_TASK_TARGET_PROJECT
935
+ };
936
+ }
937
+ try {
938
+ const vercelProjectJsonPath = fs5.readFileSync(
939
+ path4.join(opts?.packageRoot || ".", ".vercel", "project.json"),
940
+ "utf-8"
941
+ );
942
+ const projectJson = JSON.parse(vercelProjectJsonPath);
943
+ if (projectJson.projectName) {
944
+ return {
945
+ name: projectJson.projectName,
946
+ projectName: projectJson.projectName
947
+ };
948
+ }
949
+ } catch (_) {
970
950
  }
971
951
  try {
972
952
  const packageJsonString = fs5.readFileSync(
@@ -984,7 +964,7 @@ function getApplicationContext(opts) {
984
964
  }
985
965
  );
986
966
  }
987
- return { name: packageJson.name };
967
+ return { name: packageJson.name, packageJsonName: packageJson.name };
988
968
  } catch (err) {
989
969
  throw MicrofrontendError.handle(err, {
990
970
  fileName: "package.json"
@@ -1124,6 +1104,10 @@ var schema_default = {
1124
1104
  routing: {
1125
1105
  $ref: "#/definitions/Routing",
1126
1106
  description: "Groups of path expressions that are routed to this application."
1107
+ },
1108
+ assetPrefix: {
1109
+ type: "string",
1110
+ description: "The name of the asset prefix to use instead of the auto-generated name.\n\nThe asset prefix is used to prefix all paths to static assets, such as JS, CSS, or images that are served by a specific application. It is necessary to ensure there are no conflicts with other applications on the same domain.\n\nAn auto-generated asset prefix of the form `vc-ap-<hash>` is used when this field is not provided.\n\nWhen this field is provided, `/${assetPrefix}/:path*` must also be added to the list of paths in the `routing` field. Changing the asset prefix after a microfrontend application has already been deployed is not a forwards and backwards compatible change, and the asset prefix should be added to the `routing` field and deployed before setting the `assetPrefix` field."
1127
1111
  }
1128
1112
  },
1129
1113
  required: [
@@ -1349,7 +1333,7 @@ var MicrofrontendsServer = class {
1349
1333
  }
1350
1334
  try {
1351
1335
  const packageRoot = findPackageRoot(directory);
1352
- const { name: appName } = getApplicationContext({ packageRoot });
1336
+ const applicationContext = getApplicationContext({ packageRoot });
1353
1337
  const maybeConfig = findConfig({ dir: packageRoot });
1354
1338
  if (maybeConfig) {
1355
1339
  return MicrofrontendsServer.fromFile({
@@ -1383,7 +1367,7 @@ var MicrofrontendsServer = class {
1383
1367
  if (isMonorepo2) {
1384
1368
  const defaultPackage = inferMicrofrontendsLocation({
1385
1369
  repositoryRoot,
1386
- applicationName: appName
1370
+ applicationContext
1387
1371
  });
1388
1372
  const maybeConfigFromDefault = findConfig({ dir: defaultPackage });
1389
1373
  if (maybeConfigFromDefault) {
@@ -1563,6 +1547,20 @@ ${indent} - Automatically redirecting all requests to local microfrontends proxy
1563
1547
  return { next };
1564
1548
  }
1565
1549
 
1550
+ // src/next/config/transforms/transpile-packages.ts
1551
+ function transform5(args) {
1552
+ const { next } = args;
1553
+ if (next.transpilePackages === void 0 || !next.transpilePackages.includes("@vercel/microfrontends")) {
1554
+ next.transpilePackages = [
1555
+ ...next.transpilePackages || [],
1556
+ "@vercel/microfrontends"
1557
+ ];
1558
+ }
1559
+ return {
1560
+ next
1561
+ };
1562
+ }
1563
+
1566
1564
  // src/next/config/transforms/rewrites.ts
1567
1565
  function debugRewrites(rewrites) {
1568
1566
  if (process.env.MFE_DEBUG) {
@@ -1595,7 +1593,7 @@ function rewritesMapToArr(rewrites) {
1595
1593
  ];
1596
1594
  });
1597
1595
  }
1598
- function transform5(args) {
1596
+ function transform6(args) {
1599
1597
  const { app, next } = args;
1600
1598
  const buildBeforeFiles = () => {
1601
1599
  const rewrites = /* @__PURE__ */ new Map();
@@ -1679,7 +1677,7 @@ var SortChunksPlugin = class {
1679
1677
 
1680
1678
  // src/next/config/transforms/webpack.ts
1681
1679
  var nextVersion = getNextJsVersion();
1682
- function transform6(args) {
1680
+ function transform7(args) {
1683
1681
  const useDefineServer = args.opts?.preferWebpackEnvironmentPlugin ? false : semver.gte(nextVersion, "15.4.0-canary.41");
1684
1682
  const { next, microfrontend, opts } = args;
1685
1683
  const configWithWebpack = {
@@ -1763,9 +1761,132 @@ var transforms = {
1763
1761
  buildId: transform2,
1764
1762
  draftMode: transform3,
1765
1763
  redirects: transform4,
1766
- rewrites: transform5,
1767
- webpack: transform6
1764
+ rewrites: transform6,
1765
+ transpilePackages: transform5,
1766
+ webpack: transform7
1767
+ };
1768
+
1769
+ // src/config/microfrontends-config/client/index.ts
1770
+ import { pathToRegexp as pathToRegexp2 } from "path-to-regexp";
1771
+ var regexpCache = /* @__PURE__ */ new Map();
1772
+ var getRegexp = (path6) => {
1773
+ const existing = regexpCache.get(path6);
1774
+ if (existing) {
1775
+ return existing;
1776
+ }
1777
+ const regexp = pathToRegexp2(path6);
1778
+ regexpCache.set(path6, regexp);
1779
+ return regexp;
1768
1780
  };
1781
+ var MicrofrontendConfigClient = class {
1782
+ constructor(config, opts) {
1783
+ this.pathCache = {};
1784
+ this.hasFlaggedPaths = config.hasFlaggedPaths ?? false;
1785
+ for (const app of Object.values(config.applications)) {
1786
+ if (app.routing) {
1787
+ if (app.routing.some((match) => match.flag)) {
1788
+ this.hasFlaggedPaths = true;
1789
+ }
1790
+ const newRouting = [];
1791
+ const pathsWithoutFlags = [];
1792
+ for (const group of app.routing) {
1793
+ if (group.flag) {
1794
+ if (opts?.removeFlaggedPaths) {
1795
+ continue;
1796
+ }
1797
+ if (group.group) {
1798
+ delete group.group;
1799
+ }
1800
+ newRouting.push(group);
1801
+ } else {
1802
+ pathsWithoutFlags.push(...group.paths);
1803
+ }
1804
+ }
1805
+ if (pathsWithoutFlags.length > 0) {
1806
+ newRouting.push({ paths: pathsWithoutFlags });
1807
+ }
1808
+ app.routing = newRouting;
1809
+ }
1810
+ }
1811
+ this.serialized = config;
1812
+ if (this.hasFlaggedPaths) {
1813
+ this.serialized.hasFlaggedPaths = this.hasFlaggedPaths;
1814
+ }
1815
+ this.applications = config.applications;
1816
+ }
1817
+ /**
1818
+ * Create a new `MicrofrontendConfigClient` from a JSON string.
1819
+ * Config must be passed in to remain framework agnostic
1820
+ */
1821
+ static fromEnv(config) {
1822
+ if (!config) {
1823
+ throw new Error(
1824
+ "Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
1825
+ );
1826
+ }
1827
+ return new MicrofrontendConfigClient(JSON.parse(config));
1828
+ }
1829
+ isEqual(other) {
1830
+ return this === other || JSON.stringify(this.applications) === JSON.stringify(other.applications);
1831
+ }
1832
+ getApplicationNameForPath(path6) {
1833
+ if (!path6.startsWith("/")) {
1834
+ throw new Error(`Path must start with a /`);
1835
+ }
1836
+ if (this.pathCache[path6]) {
1837
+ return this.pathCache[path6];
1838
+ }
1839
+ const pathname = new URL(path6, "https://example.com").pathname;
1840
+ for (const [name, application] of Object.entries(this.applications)) {
1841
+ if (application.routing) {
1842
+ for (const group of application.routing) {
1843
+ for (const childPath of group.paths) {
1844
+ const regexp = getRegexp(childPath);
1845
+ if (regexp.test(pathname)) {
1846
+ this.pathCache[path6] = name;
1847
+ return name;
1848
+ }
1849
+ }
1850
+ }
1851
+ }
1852
+ }
1853
+ const defaultApplication = Object.entries(this.applications).find(
1854
+ ([, application]) => application.default
1855
+ );
1856
+ if (!defaultApplication) {
1857
+ return null;
1858
+ }
1859
+ this.pathCache[path6] = defaultApplication[0];
1860
+ return defaultApplication[0];
1861
+ }
1862
+ serialize() {
1863
+ return this.serialized;
1864
+ }
1865
+ };
1866
+
1867
+ // src/config/microfrontends-config/client/from-isomorphic-config.ts
1868
+ function fromIsomorphicConfig(config, options) {
1869
+ const applications = Object.fromEntries(
1870
+ Object.entries(config.childApplications).map(([name, application]) => [
1871
+ hashApplicationName(name),
1872
+ {
1873
+ default: false,
1874
+ routing: application.routing
1875
+ }
1876
+ ])
1877
+ );
1878
+ applications[hashApplicationName(config.defaultApplication.name)] = {
1879
+ default: true
1880
+ };
1881
+ return new MicrofrontendConfigClient(
1882
+ {
1883
+ applications
1884
+ },
1885
+ {
1886
+ removeFlaggedPaths: options?.removeFlaggedPaths
1887
+ }
1888
+ );
1889
+ }
1769
1890
 
1770
1891
  // src/next/config/env.ts
1771
1892
  function debugEnv(env) {
@@ -1790,8 +1911,11 @@ function setEnvironment({
1790
1911
  }) {
1791
1912
  const clientEnvs = {
1792
1913
  NEXT_PUBLIC_MFE_CURRENT_APPLICATION: app.name,
1914
+ NEXT_PUBLIC_MFE_CURRENT_APPLICATION_HASH: hashApplicationName(app.name),
1793
1915
  NEXT_PUBLIC_MFE_CLIENT_CONFIG: JSON.stringify(
1794
- microfrontends.config.toClientConfig().serialize()
1916
+ fromIsomorphicConfig(microfrontends.config, {
1917
+ removeFlaggedPaths: true
1918
+ }).serialize()
1795
1919
  ),
1796
1920
  ...process.env.ROUTE_OBSERVABILITY_TO_THIS_PROJECT && app.getAssetPrefix() ? {
1797
1921
  NEXT_PUBLIC_VERCEL_OBSERVABILITY_BASEPATH: `/${app.getAssetPrefix()}/_vercel`
@@ -1799,7 +1923,10 @@ function setEnvironment({
1799
1923
  };
1800
1924
  const serverEnvs = {
1801
1925
  MFE_CURRENT_APPLICATION: app.name,
1802
- MFE_CONFIG: JSON.stringify(microfrontends.config.getConfig())
1926
+ MFE_CONFIG: JSON.stringify(microfrontends.config.getConfig()),
1927
+ MFE_CLIENT_CONFIG_FULL: JSON.stringify(
1928
+ fromIsomorphicConfig(microfrontends.config).serialize()
1929
+ )
1803
1930
  };
1804
1931
  const allEnvs = { ...clientEnvs, ...serverEnvs };
1805
1932
  for (const [key, value] of Object.entries(allEnvs)) {
@@ -1829,13 +1956,13 @@ function withMicrofrontends(nextConfig, opts) {
1829
1956
  const app = microfrontends.config.getApplication(fromApp);
1830
1957
  setEnvironment({ app, microfrontends });
1831
1958
  let next = { ...nextConfig };
1832
- for (const [key, transform7] of typedEntries(transforms)) {
1959
+ for (const [key, transform8] of typedEntries(transforms)) {
1833
1960
  if (opts?.skipTransforms?.includes(key)) {
1834
1961
  console.log(`Skipping ${key} transform`);
1835
1962
  continue;
1836
1963
  }
1837
1964
  try {
1838
- const transformedConfig = transform7({
1965
+ const transformedConfig = transform8({
1839
1966
  app,
1840
1967
  next,
1841
1968
  microfrontend: microfrontends.config,