@vercel/microfrontends 0.10.1 → 0.12.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 (61) hide show
  1. package/dist/bin/cli.cjs +263 -102
  2. package/dist/config.cjs +0 -2
  3. package/dist/config.cjs.map +1 -1
  4. package/dist/config.js +0 -2
  5. package/dist/config.js.map +1 -1
  6. package/dist/{index-acb44057.d.ts → index-35038aec.d.ts} +2 -2
  7. package/dist/next/config.cjs +10 -3
  8. package/dist/next/config.cjs.map +1 -1
  9. package/dist/next/config.js +10 -3
  10. package/dist/next/config.js.map +1 -1
  11. package/dist/next/middleware.cjs +17 -1
  12. package/dist/next/middleware.cjs.map +1 -1
  13. package/dist/next/middleware.js +17 -1
  14. package/dist/next/middleware.js.map +1 -1
  15. package/dist/next/testing.cjs +0 -2
  16. package/dist/next/testing.cjs.map +1 -1
  17. package/dist/next/testing.js +0 -2
  18. package/dist/next/testing.js.map +1 -1
  19. package/dist/{types-c3d15d04.d.ts → types-15b7f215.d.ts} +1 -1
  20. package/dist/{types-7b1cd9f7.d.ts → types-a995174e.d.ts} +1 -4
  21. package/dist/v2/config.cjs +1 -1
  22. package/dist/v2/config.cjs.map +1 -1
  23. package/dist/v2/config.d.ts +3 -3
  24. package/dist/v2/config.js +1 -1
  25. package/dist/v2/config.js.map +1 -1
  26. package/dist/v2/microfrontends/server.cjs +215 -53
  27. package/dist/v2/microfrontends/server.cjs.map +1 -1
  28. package/dist/v2/microfrontends/server.d.ts +22 -3
  29. package/dist/v2/microfrontends/server.js +215 -53
  30. package/dist/v2/microfrontends/server.js.map +1 -1
  31. package/dist/v2/microfrontends.cjs +1 -2
  32. package/dist/v2/microfrontends.cjs.map +1 -1
  33. package/dist/v2/microfrontends.d.ts +3 -4
  34. package/dist/v2/microfrontends.js +1 -2
  35. package/dist/v2/microfrontends.js.map +1 -1
  36. package/dist/v2/next/config.cjs +249 -82
  37. package/dist/v2/next/config.cjs.map +1 -1
  38. package/dist/v2/next/config.js +249 -82
  39. package/dist/v2/next/config.js.map +1 -1
  40. package/dist/v2/next/endpoints.cjs +5 -2
  41. package/dist/v2/next/endpoints.cjs.map +1 -1
  42. package/dist/v2/next/endpoints.d.ts +1 -1
  43. package/dist/v2/next/endpoints.js +5 -2
  44. package/dist/v2/next/endpoints.js.map +1 -1
  45. package/dist/v2/next/middleware.cjs +107 -88
  46. package/dist/v2/next/middleware.cjs.map +1 -1
  47. package/dist/v2/next/middleware.js +107 -88
  48. package/dist/v2/next/middleware.js.map +1 -1
  49. package/dist/v2/overrides.cjs +1 -1
  50. package/dist/v2/overrides.cjs.map +1 -1
  51. package/dist/v2/overrides.d.ts +3 -3
  52. package/dist/v2/overrides.js +1 -1
  53. package/dist/v2/overrides.js.map +1 -1
  54. package/dist/v2/schema.d.ts +1 -1
  55. package/dist/validation.cjs +1 -11
  56. package/dist/validation.cjs.map +1 -1
  57. package/dist/validation.d.ts +0 -3
  58. package/dist/validation.js +1 -11
  59. package/dist/validation.js.map +1 -1
  60. package/package.json +8 -7
  61. package/schema/schema-v2.json +0 -14
package/dist/bin/cli.cjs CHANGED
@@ -29,7 +29,7 @@ var import_commander = require("commander");
29
29
  // package.json
30
30
  var package_default = {
31
31
  name: "@vercel/microfrontends",
32
- version: "0.10.1",
32
+ version: "0.12.0",
33
33
  private: false,
34
34
  description: "Defines configuration and utilities for micro-frontend development",
35
35
  repository: {
@@ -43,6 +43,7 @@ var package_default = {
43
43
  "micro-frontends": "./cli/index.cjs"
44
44
  },
45
45
  exports: {
46
+ "./schema.json": "./schema/schema-v2.json",
46
47
  "./validation": {
47
48
  import: "./dist/validation.js",
48
49
  require: "./dist/validation.cjs"
@@ -181,9 +182,9 @@ var package_default = {
181
182
  "@vercel-private/conformance": "^1.12.2-canary.0",
182
183
  jest: "^29.7.0",
183
184
  "jest-environment-jsdom": "29.2.2",
184
- next: "15.0.4-canary.41",
185
- react: "19.0.0-rc-de68d2f4-20241204",
186
- "react-dom": "19.0.0-rc-de68d2f4-20241204",
185
+ next: "15.1.1-canary.0",
186
+ react: "19.0.0",
187
+ "react-dom": "19.0.0",
187
188
  "ts-json-schema-generator": "^1.1.2",
188
189
  tsup: "^6.6.2",
189
190
  tsx: "^4.6.2",
@@ -191,9 +192,9 @@ var package_default = {
191
192
  webpack: "5"
192
193
  },
193
194
  peerDependencies: {
194
- next: "15.0.4-canary.41",
195
- react: "19.0.0-rc-de68d2f4-20241204",
196
- "react-dom": "19.0.0-rc-de68d2f4-20241204"
195
+ next: "15.1.1-canary.0",
196
+ react: "19.0.0",
197
+ "react-dom": "19.0.0"
197
198
  },
198
199
  publishConfig: {
199
200
  access: "restricted"
@@ -1090,8 +1091,8 @@ function validateMainPath(applicationConfigsById) {
1090
1091
  });
1091
1092
  }
1092
1093
  for (const { id: otherId, paths } of pathsWithApp) {
1093
- const isValid = paths.every((path4) => {
1094
- const matcher = (0, import_path_to_regexp.pathToRegexp)(path4);
1094
+ const isValid = paths.every((path6) => {
1095
+ const matcher = (0, import_path_to_regexp.pathToRegexp)(path6);
1095
1096
  return !matcher.test(defaultRoute);
1096
1097
  });
1097
1098
  if (!isValid) {
@@ -1103,8 +1104,8 @@ function validateMainPath(applicationConfigsById) {
1103
1104
  }
1104
1105
  } else {
1105
1106
  const allPaths = app.routing.matches.flatMap((match) => match.paths);
1106
- const isValid = allPaths.some((path4) => {
1107
- const matcher = (0, import_path_to_regexp.pathToRegexp)(path4);
1107
+ const isValid = allPaths.some((path6) => {
1108
+ const matcher = (0, import_path_to_regexp.pathToRegexp)(path6);
1108
1109
  return matcher.test(defaultRoute);
1109
1110
  });
1110
1111
  if (!isValid) {
@@ -1124,18 +1125,18 @@ var validatePaths = (applicationConfigsById) => {
1124
1125
  continue;
1125
1126
  }
1126
1127
  for (const pathMatch of app.routing.matches) {
1127
- for (const path4 of pathMatch.paths) {
1128
- const maybeError = validatePathExpression(path4);
1128
+ for (const path6 of pathMatch.paths) {
1129
+ const maybeError = validatePathExpression(path6);
1129
1130
  if (maybeError) {
1130
1131
  errors.push(maybeError);
1131
1132
  }
1132
- const existing = pathsByApplicationId.get(path4);
1133
+ const existing = pathsByApplicationId.get(path6);
1133
1134
  if (existing) {
1134
1135
  existing.applications.push(id);
1135
1136
  } else {
1136
- pathsByApplicationId.set(path4, {
1137
+ pathsByApplicationId.set(path6, {
1137
1138
  applications: [id],
1138
- matcher: (0, import_path_to_regexp.pathToRegexp)(path4),
1139
+ matcher: (0, import_path_to_regexp.pathToRegexp)(path6),
1139
1140
  applicationId: id
1140
1141
  });
1141
1142
  }
@@ -1143,10 +1144,10 @@ var validatePaths = (applicationConfigsById) => {
1143
1144
  }
1144
1145
  }
1145
1146
  const entries = Array.from(pathsByApplicationId.entries());
1146
- entries.forEach(([path4, { applications: ids, matcher, applicationId }]) => {
1147
+ entries.forEach(([path6, { applications: ids, matcher, applicationId }]) => {
1147
1148
  if (ids.length > 1) {
1148
1149
  errors.push(
1149
- `Duplicate path "${path4}" for applications "${ids.join(", ")}"`
1150
+ `Duplicate path "${path6}" for applications "${ids.join(", ")}"`
1150
1151
  );
1151
1152
  }
1152
1153
  entries.forEach(
@@ -1154,14 +1155,14 @@ var validatePaths = (applicationConfigsById) => {
1154
1155
  matchPath,
1155
1156
  { applications: matchIds, applicationId: matchApplicationId }
1156
1157
  ]) => {
1157
- if (path4 === matchPath) {
1158
+ if (path6 === matchPath) {
1158
1159
  return;
1159
1160
  }
1160
1161
  if (applicationId === matchApplicationId) {
1161
1162
  return;
1162
1163
  }
1163
1164
  if (matcher.test(matchPath)) {
1164
- const source = `"${path4}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
1165
+ const source = `"${path6}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
1165
1166
  const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
1166
1167
  errors.push(
1167
1168
  `Overlapping path detected between ${source} and ${destination}`
@@ -1178,25 +1179,25 @@ var validatePaths = (applicationConfigsById) => {
1178
1179
  }
1179
1180
  };
1180
1181
  var PATH_DEFAULT_PATTERN = "[^\\/#\\?]+?";
1181
- function validatePathExpression(path4) {
1182
- const tokens = (0, import_path_to_regexp.parse)(path4);
1182
+ function validatePathExpression(path6) {
1183
+ const tokens = (0, import_path_to_regexp.parse)(path6);
1183
1184
  for (let i = 0; i < tokens.length; i++) {
1184
1185
  const token = tokens[i];
1185
1186
  if (token === void 0) {
1186
- return `token ${i} in ${path4} is undefined, this shouldn't happen`;
1187
+ return `token ${i} in ${path6} is undefined, this shouldn't happen`;
1187
1188
  }
1188
1189
  if (typeof token !== "string") {
1189
1190
  if (token.pattern !== PATH_DEFAULT_PATTERN) {
1190
- return `Path ${path4} cannot use a regular expression wildcard`;
1191
+ return `Path ${path6} cannot use a regular expression wildcard`;
1191
1192
  }
1192
1193
  if (token.prefix !== "/") {
1193
- return `Wildcard :${token.name} must be immediately after a / in ${path4}`;
1194
+ return `Wildcard :${token.name} must be immediately after a / in ${path6}`;
1194
1195
  }
1195
1196
  if (token.suffix) {
1196
1197
  return `Wildcard suffix on :${token.name} is not allowed. Suffixes are not supported`;
1197
1198
  }
1198
1199
  if (token.modifier && i !== tokens.length - 1) {
1199
- return `Modifier ${token.modifier} is not allowed on wildcard :${token.name} in ${path4}. Modifiers are only allowed in the last path component`;
1200
+ return `Modifier ${token.modifier} is not allowed on wildcard :${token.name} in ${path6}. Modifiers are only allowed in the last path component`;
1200
1201
  }
1201
1202
  }
1202
1203
  }
@@ -1267,8 +1268,6 @@ function convertV1ConfigToV2Config(config, fromApp) {
1267
1268
  if (config.applications[fromApp].default) {
1268
1269
  return {
1269
1270
  ...common,
1270
- // this is assumed for now, and by the time this is released we won't need this conversion
1271
- provider: "vercel",
1272
1271
  applications: Object.fromEntries(
1273
1272
  Object.entries(config.applications).map(([id, application]) => [
1274
1273
  id,
@@ -1474,22 +1473,22 @@ var validateConfigPaths = (applicationConfigsById) => {
1474
1473
  continue;
1475
1474
  }
1476
1475
  for (const pathMatch of app.routing) {
1477
- for (const path4 of pathMatch.paths) {
1478
- const tokens = (0, import_path_to_regexp2.parse)(path4);
1476
+ for (const path6 of pathMatch.paths) {
1477
+ const tokens = (0, import_path_to_regexp2.parse)(path6);
1479
1478
  for (const token of tokens.slice(0, -1)) {
1480
1479
  if (typeof token !== "string") {
1481
1480
  errors.push(
1482
- `Path ${path4} may only have a :wildcard in the last path component`
1481
+ `Path ${path6} may only have a :wildcard in the last path component`
1483
1482
  );
1484
1483
  }
1485
1484
  }
1486
- const existing = pathsByApplicationId.get(path4);
1485
+ const existing = pathsByApplicationId.get(path6);
1487
1486
  if (existing) {
1488
1487
  existing.applications.push(id);
1489
1488
  } else {
1490
- pathsByApplicationId.set(path4, {
1489
+ pathsByApplicationId.set(path6, {
1491
1490
  applications: [id],
1492
- matcher: (0, import_path_to_regexp2.pathToRegexp)(path4),
1491
+ matcher: (0, import_path_to_regexp2.pathToRegexp)(path6),
1493
1492
  applicationId: id
1494
1493
  });
1495
1494
  }
@@ -1497,10 +1496,10 @@ var validateConfigPaths = (applicationConfigsById) => {
1497
1496
  }
1498
1497
  }
1499
1498
  const entries = Array.from(pathsByApplicationId.entries());
1500
- entries.forEach(([path4, { applications: ids, matcher, applicationId }]) => {
1499
+ entries.forEach(([path6, { applications: ids, matcher, applicationId }]) => {
1501
1500
  if (ids.length > 1) {
1502
1501
  errors.push(
1503
- `Duplicate path "${path4}" for applications "${ids.join(", ")}"`
1502
+ `Duplicate path "${path6}" for applications "${ids.join(", ")}"`
1504
1503
  );
1505
1504
  }
1506
1505
  entries.forEach(
@@ -1508,14 +1507,14 @@ var validateConfigPaths = (applicationConfigsById) => {
1508
1507
  matchPath,
1509
1508
  { applications: matchIds, applicationId: matchApplicationId }
1510
1509
  ]) => {
1511
- if (path4 === matchPath) {
1510
+ if (path6 === matchPath) {
1512
1511
  return;
1513
1512
  }
1514
1513
  if (applicationId === matchApplicationId) {
1515
1514
  return;
1516
1515
  }
1517
1516
  if (matcher.test(matchPath)) {
1518
- const source = `"${path4}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
1517
+ const source = `"${path6}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
1519
1518
  const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
1520
1519
  errors.push(
1521
1520
  `Overlapping path detected between ${source} and ${destination}`
@@ -1790,21 +1789,21 @@ var MicrofrontendConfigClient = class {
1790
1789
  isEqual(other) {
1791
1790
  return JSON.stringify(this.applications) === JSON.stringify(other.applications);
1792
1791
  }
1793
- getApplicationNameForPath(path4) {
1794
- if (!path4.startsWith("/")) {
1792
+ getApplicationNameForPath(path6) {
1793
+ if (!path6.startsWith("/")) {
1795
1794
  throw new Error(`Path must start with a /`);
1796
1795
  }
1797
- if (this.pathCache[path4]) {
1798
- return this.pathCache[path4];
1796
+ if (this.pathCache[path6]) {
1797
+ return this.pathCache[path6];
1799
1798
  }
1800
- const pathname = new URL(path4, "https://example.com").pathname;
1799
+ const pathname = new URL(path6, "https://example.com").pathname;
1801
1800
  for (const [name, application] of Object.entries(this.applications)) {
1802
1801
  if (application.routing) {
1803
1802
  for (const group of application.routing) {
1804
1803
  for (const childPath of group.paths) {
1805
1804
  const regexp = (0, import_path_to_regexp3.pathToRegexp)(childPath);
1806
1805
  if (regexp.test(pathname)) {
1807
- this.pathCache[path4] = name;
1806
+ this.pathCache[path6] = name;
1808
1807
  return name;
1809
1808
  }
1810
1809
  }
@@ -1817,7 +1816,7 @@ var MicrofrontendConfigClient = class {
1817
1816
  if (!defaultApplication) {
1818
1817
  return null;
1819
1818
  }
1820
- this.pathCache[path4] = defaultApplication[0];
1819
+ this.pathCache[path6] = defaultApplication[0];
1821
1820
  return defaultApplication[0];
1822
1821
  }
1823
1822
  serialize() {
@@ -1826,7 +1825,7 @@ var MicrofrontendConfigClient = class {
1826
1825
  };
1827
1826
 
1828
1827
  // src/config-v2/overrides/constants.ts
1829
- var OVERRIDES_COOKIE_PREFIX2 = "vercel-microfrontends-override";
1828
+ var OVERRIDES_COOKIE_PREFIX2 = "vercel-micro-frontends-override";
1830
1829
  var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX2}:env:`;
1831
1830
 
1832
1831
  // src/config-v2/overrides/is-override-cookie.ts
@@ -2055,7 +2054,6 @@ var MicrofrontendMainConfig = class extends MicrofrontendConfigIsomorphic {
2055
2054
  var _a, _b, _c;
2056
2055
  super({ config, overrides, meta });
2057
2056
  this.isMainConfig = true;
2058
- this.provider = config.provider;
2059
2057
  const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
2060
2058
  let defaultApplication;
2061
2059
  for (const [appId, appConfig] of Object.entries(config.applications)) {
@@ -2091,8 +2089,8 @@ function isMainConfig2(c) {
2091
2089
  }
2092
2090
 
2093
2091
  // src/config-v2/microfrontends/server/index.ts
2094
- var import_node_fs5 = __toESM(require("fs"), 1);
2095
- var import_node_path6 = require("path");
2092
+ var import_node_fs8 = __toESM(require("fs"), 1);
2093
+ var import_node_path9 = require("path");
2096
2094
 
2097
2095
  // src/config-v2/microfrontends-config/isomorphic/child.ts
2098
2096
  var MicrofrontendChildConfig = class extends MicrofrontendConfigIsomorphic {
@@ -2209,6 +2207,113 @@ function findPackagePath(opts) {
2209
2207
  return result;
2210
2208
  }
2211
2209
 
2210
+ // src/config-v2/microfrontends/utils/find-default-package.ts
2211
+ var import_node_path6 = require("path");
2212
+ var import_node_fs5 = require("fs");
2213
+ var import_fast_glob2 = __toESM(require("fast-glob"), 1);
2214
+ var configCache2 = {};
2215
+ function findDefaultMicrofrontendsPackages({
2216
+ repositoryRoot,
2217
+ applicationName
2218
+ }) {
2219
+ try {
2220
+ const microfrontendsJsonPaths = import_fast_glob2.default.globSync("**/microfrontends.json", {
2221
+ cwd: repositoryRoot,
2222
+ absolute: true,
2223
+ onlyFiles: true,
2224
+ followSymbolicLinks: false,
2225
+ ignore: ["**/node_modules/**", "**/.git/**"]
2226
+ });
2227
+ const matchingPaths = [];
2228
+ for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
2229
+ const microfrontendsJsonContent = (0, import_node_fs5.readFileSync)(
2230
+ microfrontendsJsonPath,
2231
+ "utf-8"
2232
+ );
2233
+ const microfrontendsJson = JSON.parse(
2234
+ microfrontendsJsonContent
2235
+ );
2236
+ if (isMainConfig(microfrontendsJson) && microfrontendsJson.applications[applicationName]) {
2237
+ matchingPaths.push(microfrontendsJsonPath);
2238
+ }
2239
+ }
2240
+ if (matchingPaths.length > 1) {
2241
+ throw new Error(
2242
+ `Found multiple default applications referencing "${applicationName}" in the repository, this is not yet supported.
2243
+ ${matchingPaths.join("\n \u2022 ")}`
2244
+ );
2245
+ }
2246
+ if (matchingPaths.length === 0) {
2247
+ throw new Error(
2248
+ `Could not find default application with "applications.${applicationName}"`
2249
+ );
2250
+ }
2251
+ const [packageJsonPath] = matchingPaths;
2252
+ return (0, import_node_path6.dirname)(packageJsonPath);
2253
+ } catch (error) {
2254
+ return null;
2255
+ }
2256
+ }
2257
+ function findDefaultMicrofrontendsPackage(opts) {
2258
+ const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;
2259
+ if (configCache2[cacheKey]) {
2260
+ return configCache2[cacheKey];
2261
+ }
2262
+ const result = findDefaultMicrofrontendsPackages(opts);
2263
+ if (!result) {
2264
+ throw new Error(
2265
+ `Error trying to resolve the main microfrontends.json configuration`
2266
+ );
2267
+ }
2268
+ configCache2[cacheKey] = result;
2269
+ return result;
2270
+ }
2271
+
2272
+ // src/config-v2/microfrontends/utils/is-monorepo.ts
2273
+ var import_node_fs6 = __toESM(require("fs"), 1);
2274
+ var import_node_path7 = __toESM(require("path"), 1);
2275
+ function isMonorepo({
2276
+ repositoryRoot
2277
+ }) {
2278
+ try {
2279
+ if (import_node_fs6.default.existsSync(import_node_path7.default.join(repositoryRoot, "pnpm-workspace.yaml"))) {
2280
+ return true;
2281
+ }
2282
+ if (import_node_fs6.default.existsSync(import_node_path7.default.join(repositoryRoot, "vlt-workspaces.json"))) {
2283
+ return true;
2284
+ }
2285
+ const packageJsonPath = import_node_path7.default.join(repositoryRoot, "package.json");
2286
+ if (!import_node_fs6.default.existsSync(packageJsonPath)) {
2287
+ return false;
2288
+ }
2289
+ const packageJson = JSON.parse(
2290
+ import_node_fs6.default.readFileSync(packageJsonPath, "utf-8")
2291
+ );
2292
+ return packageJson.workspaces !== void 0;
2293
+ } catch (error) {
2294
+ console.error("Error determining if repository is a monorepo", error);
2295
+ return false;
2296
+ }
2297
+ }
2298
+
2299
+ // src/config-v2/microfrontends/utils/find-package-root.ts
2300
+ var import_node_fs7 = __toESM(require("fs"), 1);
2301
+ var import_node_path8 = __toESM(require("path"), 1);
2302
+ var PACKAGE_JSON = "package.json";
2303
+ function findPackageRoot(startDir) {
2304
+ let currentDir = startDir || process.cwd();
2305
+ while (currentDir !== import_node_path8.default.parse(currentDir).root) {
2306
+ const pkgJsonPath = import_node_path8.default.join(currentDir, PACKAGE_JSON);
2307
+ if (import_node_fs7.default.existsSync(pkgJsonPath)) {
2308
+ return currentDir;
2309
+ }
2310
+ currentDir = import_node_path8.default.dirname(currentDir);
2311
+ }
2312
+ throw new Error(
2313
+ "Package root not found. Specify the root of the package with the `package.root` option."
2314
+ );
2315
+ }
2316
+
2212
2317
  // src/config-v2/microfrontends/server/validation.ts
2213
2318
  var import_jsonc_parser3 = require("jsonc-parser");
2214
2319
  var import_ajv2 = require("ajv");
@@ -2248,15 +2353,12 @@ var schema_v2_default = {
2248
2353
  },
2249
2354
  description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
2250
2355
  },
2251
- provider: {
2252
- $ref: "#/definitions/Provider"
2253
- },
2254
2356
  applications: {
2255
2357
  $ref: "#/definitions/ApplicationRouting",
2256
2358
  description: "Mapping of application names to the routes that they host. Only needs to be defined in the application that owns the primary microfrontend domain"
2257
2359
  }
2258
2360
  },
2259
- required: ["applications", "provider", "version"]
2361
+ required: ["applications", "version"]
2260
2362
  },
2261
2363
  Options: {
2262
2364
  type: "object",
@@ -2328,9 +2430,6 @@ var schema_v2_default = {
2328
2430
  projectId: {
2329
2431
  type: "string",
2330
2432
  description: "Vercel project ID"
2331
- },
2332
- routeSpeedInsightsToDefaultZone: {
2333
- type: "boolean"
2334
2433
  }
2335
2434
  },
2336
2435
  required: ["projectId"]
@@ -2433,10 +2532,6 @@ var schema_v2_default = {
2433
2532
  },
2434
2533
  required: ["paths"]
2435
2534
  },
2436
- Provider: {
2437
- type: "string",
2438
- enum: ["vercel", "other"]
2439
- },
2440
2535
  ApplicationRouting: {
2441
2536
  type: "object",
2442
2537
  additionalProperties: {
@@ -2500,8 +2595,8 @@ var MicrofrontendsServer = class extends Microfrontends {
2500
2595
  pretty: true
2501
2596
  }) {
2502
2597
  const outputPath = getOutputFilePath();
2503
- import_node_fs5.default.mkdirSync((0, import_node_path6.dirname)(outputPath), { recursive: true });
2504
- import_node_fs5.default.writeFileSync(
2598
+ import_node_fs8.default.mkdirSync((0, import_node_path9.dirname)(outputPath), { recursive: true });
2599
+ import_node_fs8.default.writeFileSync(
2505
2600
  outputPath,
2506
2601
  JSON.stringify(
2507
2602
  this.config.toSchemaJson(),
@@ -2563,6 +2658,69 @@ var MicrofrontendsServer = class extends Microfrontends {
2563
2658
  }
2564
2659
  return config;
2565
2660
  }
2661
+ /**
2662
+ * Looks up the configuration by inferring the package root and looking for a microfrontends.json file. If a file is not found,
2663
+ * it will look for a package in the repository with a microfrontends.json file that contains the current application
2664
+ * and use that configuration.
2665
+ *
2666
+ * This can return either a Child or Main configuration.
2667
+ */
2668
+ static infer({
2669
+ directory,
2670
+ filePath,
2671
+ meta,
2672
+ cookies,
2673
+ options
2674
+ } = {}) {
2675
+ if (filePath && meta) {
2676
+ return MicrofrontendsServer.fromFile({
2677
+ filePath,
2678
+ cookies,
2679
+ meta,
2680
+ options
2681
+ });
2682
+ }
2683
+ try {
2684
+ const packageRoot = findPackageRoot(directory);
2685
+ const packageJsonPath = (0, import_node_path9.join)(packageRoot, "package.json");
2686
+ const packageJson = JSON.parse(
2687
+ import_node_fs8.default.readFileSync(packageJsonPath, "utf-8")
2688
+ );
2689
+ if (!packageJson.name) {
2690
+ throw new Error(`No name found in package.json at ${packageJsonPath}`);
2691
+ }
2692
+ const configMeta = meta ?? { fromApp: packageJson.name };
2693
+ const maybeConfig = (0, import_node_path9.join)(packageRoot, "microfrontends.json");
2694
+ if (import_node_fs8.default.existsSync(maybeConfig)) {
2695
+ return MicrofrontendsServer.fromFile({
2696
+ filePath: maybeConfig,
2697
+ cookies,
2698
+ meta: configMeta,
2699
+ options
2700
+ });
2701
+ }
2702
+ const repositoryRoot = findRepositoryRoot();
2703
+ const isMonorepo2 = isMonorepo({ repositoryRoot });
2704
+ if (isMonorepo2) {
2705
+ const defaultPackage = findDefaultMicrofrontendsPackage({
2706
+ repositoryRoot,
2707
+ applicationName: packageJson.name
2708
+ });
2709
+ return MicrofrontendsServer.fromFile({
2710
+ filePath: (0, import_node_path9.join)(defaultPackage, "microfrontends.json"),
2711
+ cookies,
2712
+ meta: configMeta,
2713
+ options
2714
+ });
2715
+ }
2716
+ throw new Error("Unable to infer");
2717
+ } catch (e) {
2718
+ throw new MicrofrontendError2(
2719
+ "Unable to infer microfrontends configuration",
2720
+ { type: "config", subtype: "inference_failed" }
2721
+ );
2722
+ }
2723
+ }
2566
2724
  /*
2567
2725
  * Generates a MicrofrontendsServer instance from a file.
2568
2726
  */
@@ -2573,25 +2731,28 @@ var MicrofrontendsServer = class extends Microfrontends {
2573
2731
  options
2574
2732
  }) {
2575
2733
  try {
2576
- const configJson = import_node_fs5.default.readFileSync(filePath, "utf-8");
2734
+ const configJson = import_node_fs8.default.readFileSync(filePath, "utf-8");
2577
2735
  const config = MicrofrontendsServer.validate(configJson);
2578
2736
  if (!isMainConfig(config) && (options == null ? void 0 : options.resolveMainConfig)) {
2579
2737
  const repositoryRoot = findRepositoryRoot();
2580
- const packagePath = findPackagePath({
2581
- repositoryRoot,
2582
- name: config.partOf
2583
- });
2584
- if (!packagePath) {
2585
- throw new MicrofrontendError2(
2586
- `Could not find default application "${config.partOf}" in the repository`,
2587
- { type: "config", subtype: "not_found" }
2588
- );
2738
+ const isMonorepo2 = isMonorepo({ repositoryRoot });
2739
+ if (isMonorepo2) {
2740
+ const packagePath = findPackagePath({
2741
+ repositoryRoot,
2742
+ name: config.partOf
2743
+ });
2744
+ if (!packagePath) {
2745
+ throw new MicrofrontendError2(
2746
+ `Could not find default application "${config.partOf}" in the repository`,
2747
+ { type: "config", subtype: "not_found" }
2748
+ );
2749
+ }
2750
+ const mainConfigPath = (0, import_node_path9.join)(packagePath, "microfrontends.json");
2751
+ return MicrofrontendsServer.fromMainConfigFile({
2752
+ filePath: mainConfigPath,
2753
+ overrides: cookies ? parseOverrides(cookies) : void 0
2754
+ });
2589
2755
  }
2590
- const mainConfigPath = (0, import_node_path6.join)(packagePath, "microfrontends.json");
2591
- return MicrofrontendsServer.fromMainConfigFile({
2592
- filePath: mainConfigPath,
2593
- overrides: cookies ? parseOverrides(cookies) : void 0
2594
- });
2595
2756
  }
2596
2757
  return new MicrofrontendsServer({
2597
2758
  config,
@@ -2612,7 +2773,7 @@ var MicrofrontendsServer = class extends Microfrontends {
2612
2773
  overrides
2613
2774
  }) {
2614
2775
  try {
2615
- const config = import_node_fs5.default.readFileSync(filePath, "utf-8");
2776
+ const config = import_node_fs8.default.readFileSync(filePath, "utf-8");
2616
2777
  const validatedConfig = MicrofrontendsServer.validate(config);
2617
2778
  if (!isMainConfig(validatedConfig)) {
2618
2779
  throw new MicrofrontendError2(
@@ -2746,7 +2907,7 @@ var LocalProxy = class {
2746
2907
  const isJWTRedirect = url.searchParams.has("_vercel_jwt");
2747
2908
  const defaultHost = this.getDefaultHost(config);
2748
2909
  let hostname = null;
2749
- let path4 = request2.url;
2910
+ let path6 = request2.url;
2750
2911
  if (isAuthRedirect) {
2751
2912
  hostname = url.searchParams.get("_host_override");
2752
2913
  }
@@ -2756,12 +2917,12 @@ var LocalProxy = class {
2756
2917
  if (isJWTRedirect) {
2757
2918
  hostname = url.searchParams.get("_host_override");
2758
2919
  url.searchParams.delete("_host_override");
2759
- path4 = `${url.pathname}${url.search}`;
2920
+ path6 = `${url.pathname}${url.search}`;
2760
2921
  }
2761
2922
  if (!hostname) {
2762
2923
  return void 0;
2763
2924
  }
2764
- return { ...defaultHost, path: path4, hostname, protocol: "https", port: 443 };
2925
+ return { ...defaultHost, path: path6, hostname, protocol: "https", port: 443 };
2765
2926
  }
2766
2927
  getConfigWithOverrides(cookies) {
2767
2928
  if (isV2Config(this.config)) {
@@ -2792,19 +2953,19 @@ var LocalProxy = class {
2792
2953
  getTarget(request2) {
2793
2954
  const cookies = (0, import_cookie.parse)(request2.headers.cookie || "");
2794
2955
  const config = this.getConfigWithOverrides(cookies);
2795
- const path4 = request2.url;
2796
- if (!path4) {
2956
+ const path6 = request2.url;
2957
+ if (!path6) {
2797
2958
  return this.getDefaultHost(config);
2798
2959
  }
2799
2960
  const authTarget = this.getAuthTarget(request2, config);
2800
2961
  if (authTarget) {
2801
2962
  return authTarget;
2802
2963
  }
2803
- const url = new URL(`http://example.com${path4}`);
2964
+ const url = new URL(`http://example.com${path6}`);
2804
2965
  const pathname = url.pathname;
2805
2966
  if (isV2Config(config)) {
2806
2967
  const target = this.findMatchingApplicationV2(
2807
- path4,
2968
+ path6,
2808
2969
  pathname,
2809
2970
  config.getChildApplications()
2810
2971
  );
@@ -2812,7 +2973,7 @@ var LocalProxy = class {
2812
2973
  return target;
2813
2974
  } else {
2814
2975
  const target = this.findMatchingApplicationV1(
2815
- path4,
2976
+ path6,
2816
2977
  pathname,
2817
2978
  config.getAllApplications()
2818
2979
  );
@@ -2821,11 +2982,11 @@ var LocalProxy = class {
2821
2982
  }
2822
2983
  const defaultHost = this.getDefaultHost(config);
2823
2984
  mfeDebug(
2824
- `no matching routes, routing ${path4} to default application: ${JSON.stringify(defaultHost)}`
2985
+ `no matching routes, routing ${path6} to default application: ${JSON.stringify(defaultHost)}`
2825
2986
  );
2826
- return { path: path4, ...defaultHost };
2987
+ return { path: path6, ...defaultHost };
2827
2988
  }
2828
- findMatchingApplicationV1(path4, pathname, applications) {
2989
+ findMatchingApplicationV1(path6, pathname, applications) {
2829
2990
  for (const application of Object.values(applications)) {
2830
2991
  if (application.routing) {
2831
2992
  for (const group of application.routing.matches) {
@@ -2834,9 +2995,9 @@ var LocalProxy = class {
2834
2995
  if (regexp.test(pathname)) {
2835
2996
  const target = this.getApplicationTarget(application);
2836
2997
  mfeDebug(
2837
- `routing ${path4} to '${target.application}' at ${target.hostname}`
2998
+ `routing ${path6} to '${target.application}' at ${target.hostname}`
2838
2999
  );
2839
- return { path: path4, ...target };
3000
+ return { path: path6, ...target };
2840
3001
  }
2841
3002
  }
2842
3003
  if (application.routing.assetPrefix) {
@@ -2846,9 +3007,9 @@ var LocalProxy = class {
2846
3007
  if (pattern.test(pathname)) {
2847
3008
  const target = this.getApplicationTarget(application);
2848
3009
  mfeDebug(
2849
- `routing ${path4} to '${target.application}' at ${target.hostname}`
3010
+ `routing ${path6} to '${target.application}' at ${target.hostname}`
2850
3011
  );
2851
- return { path: path4, ...target };
3012
+ return { path: path6, ...target };
2852
3013
  }
2853
3014
  }
2854
3015
  }
@@ -2856,7 +3017,7 @@ var LocalProxy = class {
2856
3017
  }
2857
3018
  return null;
2858
3019
  }
2859
- findMatchingApplicationV2(path4, pathname, applications) {
3020
+ findMatchingApplicationV2(path6, pathname, applications) {
2860
3021
  for (const application of Object.values(applications)) {
2861
3022
  for (const group of application.routing) {
2862
3023
  for (const childPath of group.paths) {
@@ -2864,9 +3025,9 @@ var LocalProxy = class {
2864
3025
  if (regexp.test(pathname)) {
2865
3026
  const target = this.getApplicationTarget(application);
2866
3027
  mfeDebug(
2867
- `routing ${path4} to '${target.application}' at ${target.hostname}`
3028
+ `routing ${path6} to '${target.application}' at ${target.hostname}`
2868
3029
  );
2869
- return { path: path4, ...target };
3030
+ return { path: path6, ...target };
2870
3031
  }
2871
3032
  }
2872
3033
  }
@@ -2875,11 +3036,11 @@ var LocalProxy = class {
2875
3036
  }
2876
3037
  // Handles requests that return data from the local proxy itself.
2877
3038
  // Returns true if the request was handled, false otherwise.
2878
- handleProxyInfoRequest(path4, res) {
2879
- if (!path4) {
3039
+ handleProxyInfoRequest(path6, res) {
3040
+ if (!path6) {
2880
3041
  return false;
2881
3042
  }
2882
- const url = new URL(`http://example.comf${path4}`);
3043
+ const url = new URL(`http://example.comf${path6}`);
2883
3044
  const pathname = url.pathname;
2884
3045
  switch (pathname) {
2885
3046
  case "/.well-known/vercel/microfrontend-routing": {
@@ -2907,10 +3068,10 @@ var LocalProxy = class {
2907
3068
  }
2908
3069
  const target = this.getTarget(req);
2909
3070
  if (target.protocol === "https") {
2910
- const { hostname, port, path: path4 } = target;
3071
+ const { hostname, port, path: path6 } = target;
2911
3072
  const requestOptions = {
2912
3073
  hostname,
2913
- path: path4,
3074
+ path: path6,
2914
3075
  method: req.method,
2915
3076
  headers: {
2916
3077
  ...req.headers,
@@ -2938,7 +3099,7 @@ var LocalProxy = class {
2938
3099
  console.error("Proxy request error: ", err);
2939
3100
  res.writeHead(500, { "Content-Type": "text/plain" });
2940
3101
  res.end(
2941
- `Error proxying request for ${target.application} to ${hostname}:${port}${path4}`
3102
+ `Error proxying request for ${target.application} to ${hostname}:${port}${path6}`
2942
3103
  );
2943
3104
  });
2944
3105
  } else {