@vercel/microfrontends 1.0.1-canary.2 → 1.0.1-canary.4

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 (44) hide show
  1. package/dist/bin/cli.cjs +115 -85
  2. package/dist/config.cjs +5 -6
  3. package/dist/config.cjs.map +1 -1
  4. package/dist/config.d.ts +1 -1
  5. package/dist/config.js +5 -6
  6. package/dist/config.js.map +1 -1
  7. package/dist/experimental/sveltekit.cjs +81 -78
  8. package/dist/experimental/sveltekit.cjs.map +1 -1
  9. package/dist/experimental/sveltekit.js +81 -78
  10. package/dist/experimental/sveltekit.js.map +1 -1
  11. package/dist/experimental/vite.cjs +124 -88
  12. package/dist/experimental/vite.cjs.map +1 -1
  13. package/dist/experimental/vite.d.ts +1 -1
  14. package/dist/experimental/vite.js +124 -90
  15. package/dist/experimental/vite.js.map +1 -1
  16. package/dist/{index-d5994ac5.d.ts → index-2b59c627.d.ts} +1 -1
  17. package/dist/microfrontends/server.cjs +81 -51
  18. package/dist/microfrontends/server.cjs.map +1 -1
  19. package/dist/microfrontends/server.d.ts +1 -1
  20. package/dist/microfrontends/server.js +81 -51
  21. package/dist/microfrontends/server.js.map +1 -1
  22. package/dist/microfrontends.cjs +5 -6
  23. package/dist/microfrontends.cjs.map +1 -1
  24. package/dist/microfrontends.d.ts +1 -1
  25. package/dist/microfrontends.js +5 -6
  26. package/dist/microfrontends.js.map +1 -1
  27. package/dist/next/config.cjs +81 -78
  28. package/dist/next/config.cjs.map +1 -1
  29. package/dist/next/config.js +81 -78
  30. package/dist/next/config.js.map +1 -1
  31. package/dist/next/middleware.cjs +5 -6
  32. package/dist/next/middleware.cjs.map +1 -1
  33. package/dist/next/middleware.js +5 -6
  34. package/dist/next/middleware.js.map +1 -1
  35. package/dist/next/testing.cjs +5 -6
  36. package/dist/next/testing.cjs.map +1 -1
  37. package/dist/next/testing.d.ts +1 -1
  38. package/dist/next/testing.js +5 -6
  39. package/dist/next/testing.js.map +1 -1
  40. package/dist/utils/mfe-port.cjs +85 -55
  41. package/dist/utils/mfe-port.cjs.map +1 -1
  42. package/dist/utils/mfe-port.js +85 -55
  43. package/dist/utils/mfe-port.js.map +1 -1
  44. package/package.json +2 -2
@@ -33,13 +33,10 @@ __export(vite_exports, {
33
33
  microfrontends: () => microfrontends
34
34
  });
35
35
  module.exports = __toCommonJS(vite_exports);
36
- var import_node_fs9 = require("fs");
37
- var import_node_path9 = require("path");
38
- var import_node_process = require("process");
39
36
 
40
37
  // src/config/microfrontends/server/index.ts
41
- var import_node_fs7 = __toESM(require("fs"), 1);
42
- var import_node_path8 = require("path");
38
+ var import_node_fs8 = __toESM(require("fs"), 1);
39
+ var import_node_path9 = require("path");
43
40
 
44
41
  // src/config/overrides/constants.ts
45
42
  var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
@@ -222,21 +219,21 @@ var MicrofrontendConfigClient = class {
222
219
  isEqual(other) {
223
220
  return JSON.stringify(this.applications) === JSON.stringify(other.applications);
224
221
  }
225
- getApplicationNameForPath(path5) {
226
- if (!path5.startsWith("/")) {
222
+ getApplicationNameForPath(path6) {
223
+ if (!path6.startsWith("/")) {
227
224
  throw new Error(`Path must start with a /`);
228
225
  }
229
- if (this.pathCache[path5]) {
230
- return this.pathCache[path5];
226
+ if (this.pathCache[path6]) {
227
+ return this.pathCache[path6];
231
228
  }
232
- const pathname = new URL(path5, "https://example.com").pathname;
229
+ const pathname = new URL(path6, "https://example.com").pathname;
233
230
  for (const [name, application] of Object.entries(this.applications)) {
234
231
  if (application.routing) {
235
232
  for (const group of application.routing) {
236
233
  for (const childPath of group.paths) {
237
234
  const regexp = (0, import_path_to_regexp.pathToRegexp)(childPath);
238
235
  if (regexp.test(pathname)) {
239
- this.pathCache[path5] = name;
236
+ this.pathCache[path6] = name;
240
237
  return name;
241
238
  }
242
239
  }
@@ -249,7 +246,7 @@ var MicrofrontendConfigClient = class {
249
246
  if (!defaultApplication) {
250
247
  return null;
251
248
  }
252
- this.pathCache[path5] = defaultApplication[0];
249
+ this.pathCache[path6] = defaultApplication[0];
253
250
  return defaultApplication[0];
254
251
  }
255
252
  serialize() {
@@ -271,18 +268,18 @@ var validateConfigPaths = (applicationConfigsById) => {
271
268
  }
272
269
  const childApp = app;
273
270
  for (const pathMatch of childApp.routing) {
274
- for (const path5 of pathMatch.paths) {
275
- const maybeError = validatePathExpression(path5);
271
+ for (const path6 of pathMatch.paths) {
272
+ const maybeError = validatePathExpression(path6);
276
273
  if (maybeError) {
277
274
  errors.push(maybeError);
278
275
  } else {
279
- const existing = pathsByApplicationId.get(path5);
276
+ const existing = pathsByApplicationId.get(path6);
280
277
  if (existing) {
281
278
  existing.applications.push(id);
282
279
  } else {
283
- pathsByApplicationId.set(path5, {
280
+ pathsByApplicationId.set(path6, {
284
281
  applications: [id],
285
- matcher: (0, import_path_to_regexp2.pathToRegexp)(path5),
282
+ matcher: (0, import_path_to_regexp2.pathToRegexp)(path6),
286
283
  applicationId: id
287
284
  });
288
285
  }
@@ -291,24 +288,24 @@ var validateConfigPaths = (applicationConfigsById) => {
291
288
  }
292
289
  }
293
290
  const entries = Array.from(pathsByApplicationId.entries());
294
- for (const [path5, { applications: ids, matcher, applicationId }] of entries) {
291
+ for (const [path6, { applications: ids, matcher, applicationId }] of entries) {
295
292
  if (ids.length > 1) {
296
293
  errors.push(
297
- `Duplicate path "${path5}" for applications "${ids.join(", ")}"`
294
+ `Duplicate path "${path6}" for applications "${ids.join(", ")}"`
298
295
  );
299
296
  }
300
297
  for (const [
301
298
  matchPath,
302
299
  { applications: matchIds, applicationId: matchApplicationId }
303
300
  ] of entries) {
304
- if (path5 === matchPath) {
301
+ if (path6 === matchPath) {
305
302
  continue;
306
303
  }
307
304
  if (applicationId === matchApplicationId) {
308
305
  continue;
309
306
  }
310
307
  if (matcher.test(matchPath)) {
311
- const source = `"${path5}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
308
+ const source = `"${path6}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
312
309
  const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
313
310
  errors.push(
314
311
  `Overlapping path detected between ${source} and ${destination}`
@@ -324,39 +321,42 @@ var validateConfigPaths = (applicationConfigsById) => {
324
321
  }
325
322
  };
326
323
  var PATH_DEFAULT_PATTERN = "[^\\/#\\?]+?";
327
- function validatePathExpression(path5) {
324
+ function validatePathExpression(path6) {
328
325
  try {
329
- const tokens = (0, import_path_to_regexp2.parse)(path5);
330
- if (/(?<!\\)\{/.test(path5)) {
331
- return `Optional paths are not supported: ${path5}`;
326
+ const tokens = (0, import_path_to_regexp2.parse)(path6);
327
+ if (/(?<!\\)\{/.test(path6)) {
328
+ return `Optional paths are not supported: ${path6}`;
332
329
  }
333
- if (/(?<!\\|\()\?/.test(path5)) {
334
- return `Optional paths are not supported: ${path5}`;
330
+ if (/(?<!\\|\()\?/.test(path6)) {
331
+ return `Optional paths are not supported: ${path6}`;
335
332
  }
336
- if (/\/[^/]*(?<!\\):[^/]*(?<!\\):[^/]*/.test(path5)) {
337
- return `Only one wildcard is allowed per path segment: ${path5}`;
333
+ if (/\/[^/]*(?<!\\):[^/]*(?<!\\):[^/]*/.test(path6)) {
334
+ return `Only one wildcard is allowed per path segment: ${path6}`;
338
335
  }
339
336
  for (let i = 0; i < tokens.length; i++) {
340
337
  const token = tokens[i];
341
338
  if (token === void 0) {
342
- return `token ${i} in ${path5} is undefined, this shouldn't happen`;
339
+ return `token ${i} in ${path6} is undefined, this shouldn't happen`;
343
340
  }
344
341
  if (typeof token !== "string") {
342
+ if (!token.name) {
343
+ return `Only named wildcards are allowed: ${path6} (hint: add ":path" to the wildcard)`;
344
+ }
345
345
  if (token.pattern !== PATH_DEFAULT_PATTERN && // Allows (a|b|c) and ((?!a|b|c).*) regex
346
346
  // Only limited regex is supported for now, due to performance considerations
347
347
  !/^(?<allowed>[\w]+(?:\|[^|()]+)+)$|^\(\?!(?<disallowed>[\w]+(?:\|[^|()]+)+)\)\.\*$/.test(
348
348
  token.pattern
349
349
  )) {
350
- return `Path ${path5} cannot use unsupported regular expression wildcard`;
350
+ return `Path ${path6} cannot use unsupported regular expression wildcard`;
351
351
  }
352
352
  if (token.modifier && i !== tokens.length - 1) {
353
- return `Modifier ${token.modifier} is not allowed on wildcard :${token.name} in ${path5}. Modifiers are only allowed in the last path component`;
353
+ return `Modifier ${token.modifier} is not allowed on wildcard :${token.name} in ${path6}. Modifiers are only allowed in the last path component`;
354
354
  }
355
355
  }
356
356
  }
357
357
  } catch (e) {
358
358
  const message = e instanceof Error ? e.message : String(e);
359
- return `Path ${path5} could not be parsed into regexp: ${message}`;
359
+ return `Path ${path6} could not be parsed into regexp: ${message}`;
360
360
  }
361
361
  return void 0;
362
362
  }
@@ -710,12 +710,8 @@ var MicrofrontendConfigIsomorphic = class {
710
710
  const skipValidation = opts?.skipValidation ?? [];
711
711
  const c = typeof config === "string" ? (0, import_jsonc_parser.parse)(config) : config;
712
712
  if (isMainConfig(c)) {
713
- if (!skipValidation.includes("paths")) {
714
- validateConfigPaths(c.applications);
715
- }
716
- if (!skipValidation.includes("defaultApplication")) {
717
- validateConfigDefaultApplication(c.applications);
718
- }
713
+ validateConfigPaths(c.applications);
714
+ validateConfigDefaultApplication(c.applications);
719
715
  if (!skipValidation.includes("deprecatedFields")) {
720
716
  validateDeprecatedFields(c);
721
717
  }
@@ -1072,6 +1068,9 @@ function isMonorepo({
1072
1068
  if (import_node_fs4.default.existsSync(import_node_path4.default.join(repositoryRoot, "vlt-workspaces.json"))) {
1073
1069
  return true;
1074
1070
  }
1071
+ if (process.env.NX_WORKSPACE_ROOT === import_node_path4.default.resolve(repositoryRoot)) {
1072
+ return true;
1073
+ }
1075
1074
  const packageJsonPath = import_node_path4.default.join(repositoryRoot, "package.json");
1076
1075
  if (!import_node_fs4.default.existsSync(packageJsonPath)) {
1077
1076
  return false;
@@ -1117,8 +1116,42 @@ function findConfig({ dir }) {
1117
1116
  return null;
1118
1117
  }
1119
1118
 
1120
- // src/config/microfrontends/server/utils/get-output-file-path.ts
1119
+ // src/config/microfrontends/utils/get-application-context.ts
1120
+ var import_node_fs7 = __toESM(require("fs"), 1);
1121
1121
  var import_node_path7 = __toESM(require("path"), 1);
1122
+ function getApplicationContext(opts) {
1123
+ if (opts?.appName) {
1124
+ return { name: opts.appName };
1125
+ }
1126
+ if (process.env.NX_TASK_TARGET_PROJECT) {
1127
+ return { name: process.env.NX_TASK_TARGET_PROJECT };
1128
+ }
1129
+ try {
1130
+ const packageJsonString = import_node_fs7.default.readFileSync(
1131
+ import_node_path7.default.join(opts?.packageRoot || ".", "package.json"),
1132
+ "utf-8"
1133
+ );
1134
+ const packageJson = JSON.parse(packageJsonString);
1135
+ if (!packageJson.name) {
1136
+ throw new MicrofrontendError(
1137
+ `package.json file missing required field "name"`,
1138
+ {
1139
+ type: "packageJson",
1140
+ subtype: "missing_field_name",
1141
+ source: "@vercel/microfrontends/next"
1142
+ }
1143
+ );
1144
+ }
1145
+ return { name: packageJson.name };
1146
+ } catch (err) {
1147
+ throw MicrofrontendError.handle(err, {
1148
+ fileName: "package.json"
1149
+ });
1150
+ }
1151
+ }
1152
+
1153
+ // src/config/microfrontends/server/utils/get-output-file-path.ts
1154
+ var import_node_path8 = __toESM(require("path"), 1);
1122
1155
 
1123
1156
  // src/config/microfrontends/server/constants.ts
1124
1157
  var MFE_CONFIG_DEFAULT_FILE_PATH = "microfrontends";
@@ -1126,7 +1159,7 @@ var MFE_CONFIG_DEFAULT_FILE_NAME = "microfrontends.json";
1126
1159
 
1127
1160
  // src/config/microfrontends/server/utils/get-output-file-path.ts
1128
1161
  function getOutputFilePath() {
1129
- return import_node_path7.default.join(MFE_CONFIG_DEFAULT_FILE_PATH, MFE_CONFIG_DEFAULT_FILE_NAME);
1162
+ return import_node_path8.default.join(MFE_CONFIG_DEFAULT_FILE_PATH, MFE_CONFIG_DEFAULT_FILE_NAME);
1130
1163
  }
1131
1164
 
1132
1165
  // src/config/microfrontends/server/validation.ts
@@ -1465,8 +1498,8 @@ var MicrofrontendsServer = class extends Microfrontends {
1465
1498
  pretty: true
1466
1499
  }) {
1467
1500
  const outputPath = getOutputFilePath();
1468
- import_node_fs7.default.mkdirSync((0, import_node_path8.dirname)(outputPath), { recursive: true });
1469
- import_node_fs7.default.writeFileSync(
1501
+ import_node_fs8.default.mkdirSync((0, import_node_path9.dirname)(outputPath), { recursive: true });
1502
+ import_node_fs8.default.writeFileSync(
1470
1503
  outputPath,
1471
1504
  JSON.stringify(
1472
1505
  this.config.toSchemaJson(),
@@ -1552,14 +1585,8 @@ var MicrofrontendsServer = class extends Microfrontends {
1552
1585
  }
1553
1586
  try {
1554
1587
  const packageRoot = findPackageRoot(directory);
1555
- const packageJsonPath = (0, import_node_path8.join)(packageRoot, "package.json");
1556
- const packageJson = JSON.parse(
1557
- import_node_fs7.default.readFileSync(packageJsonPath, "utf-8")
1558
- );
1559
- if (!packageJson.name) {
1560
- throw new Error(`No name found in package.json at ${packageJsonPath}`);
1561
- }
1562
- const configMeta = meta ?? { fromApp: packageJson.name };
1588
+ const { name: appName } = getApplicationContext({ packageRoot });
1589
+ const configMeta = meta ?? { fromApp: appName };
1563
1590
  const maybeConfig = findConfig({ dir: packageRoot });
1564
1591
  if (maybeConfig) {
1565
1592
  return MicrofrontendsServer.fromFile({
@@ -1574,7 +1601,7 @@ var MicrofrontendsServer = class extends Microfrontends {
1574
1601
  if (isMonorepo2) {
1575
1602
  const defaultPackage = findDefaultMicrofrontendsPackage({
1576
1603
  repositoryRoot,
1577
- applicationName: packageJson.name
1604
+ applicationName: appName
1578
1605
  });
1579
1606
  const maybeConfigFromDefault = findConfig({ dir: defaultPackage });
1580
1607
  if (maybeConfigFromDefault) {
@@ -1604,7 +1631,7 @@ var MicrofrontendsServer = class extends Microfrontends {
1604
1631
  options
1605
1632
  }) {
1606
1633
  try {
1607
- const configJson = import_node_fs7.default.readFileSync(filePath, "utf-8");
1634
+ const configJson = import_node_fs8.default.readFileSync(filePath, "utf-8");
1608
1635
  const config = MicrofrontendsServer.validate(configJson);
1609
1636
  if (!isMainConfig(config) && options?.resolveMainConfig) {
1610
1637
  const repositoryRoot = findRepositoryRoot();
@@ -1652,7 +1679,7 @@ var MicrofrontendsServer = class extends Microfrontends {
1652
1679
  overrides
1653
1680
  }) {
1654
1681
  try {
1655
- const config = import_node_fs7.default.readFileSync(filePath, "utf-8");
1682
+ const config = import_node_fs8.default.readFileSync(filePath, "utf-8");
1656
1683
  const validatedConfig = MicrofrontendsServer.validate(config);
1657
1684
  if (!isMainConfig(validatedConfig)) {
1658
1685
  throw new MicrofrontendError(
@@ -1683,31 +1710,18 @@ var MicrofrontendsServer = class extends Microfrontends {
1683
1710
  }
1684
1711
  };
1685
1712
 
1686
- // src/config/microfrontends/utils/get-application-context.ts
1687
- var import_node_fs8 = __toESM(require("fs"), 1);
1688
- function getApplicationContext(opts) {
1689
- if (opts?.appName) {
1690
- return { name: opts.appName };
1713
+ // src/vite/detect-framework.ts
1714
+ var import_node_fs9 = require("fs");
1715
+ var import_node_path10 = require("path");
1716
+ var import_node_process = require("process");
1717
+ function detectFramework() {
1718
+ if ((0, import_node_fs9.existsSync)((0, import_node_path10.join)((0, import_node_process.cwd)(), "svelte.config.js"))) {
1719
+ return "sveltekit";
1691
1720
  }
1692
- try {
1693
- const packageJsonString = import_node_fs8.default.readFileSync("./package.json", "utf-8");
1694
- const packageJson = JSON.parse(packageJsonString);
1695
- if (!packageJson.name) {
1696
- throw new MicrofrontendError(
1697
- `package.json file missing required field "name"`,
1698
- {
1699
- type: "packageJson",
1700
- subtype: "missing_field_name",
1701
- source: "@vercel/microfrontends/next"
1702
- }
1703
- );
1704
- }
1705
- return { name: packageJson.name };
1706
- } catch (err) {
1707
- throw MicrofrontendError.handle(err, {
1708
- fileName: "package.json"
1709
- });
1721
+ if ((0, import_node_fs9.existsSync)((0, import_node_path10.join)((0, import_node_process.cwd)(), "react-router.config.js")) || (0, import_node_fs9.existsSync)((0, import_node_path10.join)((0, import_node_process.cwd)(), "react-router.config.ts"))) {
1722
+ return "react-router";
1710
1723
  }
1724
+ return "unknown";
1711
1725
  }
1712
1726
 
1713
1727
  // src/vite/index.ts
@@ -1719,23 +1733,45 @@ function microfrontends(opts) {
1719
1733
  }
1720
1734
  });
1721
1735
  const app = microfrontendsObj.config.getApplication(fromApp);
1736
+ if (app.isDefault() && opts?.basePath) {
1737
+ throw new Error(
1738
+ "`basePath` can not be set for the default microfrontends application."
1739
+ );
1740
+ }
1741
+ if (opts?.basePath && !opts.basePath.startsWith("/")) {
1742
+ throw new Error("`basePath` must start with a `/`");
1743
+ }
1722
1744
  const additionalConfigOptions = {};
1745
+ const framework = detectFramework();
1723
1746
  if (!app.isDefault()) {
1724
1747
  if (opts?.basePath) {
1725
- additionalConfigOptions.base = `/${opts.basePath}`;
1726
- } else {
1727
- const isSvelteKit = (0, import_node_fs9.existsSync)((0, import_node_path9.join)((0, import_node_process.cwd)(), "svelte.config.js"));
1728
- if (!isSvelteKit) {
1729
- additionalConfigOptions.experimental = {
1730
- renderBuiltUrl(filename, { type }) {
1731
- if (type === "asset") {
1732
- return `/${app.getAssetPrefix()}/${filename}`;
1733
- }
1734
- }
1735
- };
1748
+ if (framework !== "react-router" || !process.env.VERCEL_ENV) {
1749
+ let basePath = opts.basePath;
1750
+ if (process.env.NODE_ENV === "production" && !basePath.endsWith("/")) {
1751
+ basePath = `${basePath}/`;
1752
+ }
1753
+ additionalConfigOptions.base = basePath;
1736
1754
  }
1755
+ } else if (framework !== "sveltekit") {
1756
+ additionalConfigOptions.experimental = {
1757
+ renderBuiltUrl(filename, { type }) {
1758
+ if (type === "asset") {
1759
+ return `/${app.getAssetPrefix()}/${filename}`;
1760
+ }
1761
+ }
1762
+ };
1763
+ }
1764
+ if (framework === "react-router") {
1765
+ additionalConfigOptions.build = {
1766
+ assetsDir: `./${opts?.basePath ?? app.getAssetPrefix()}`
1767
+ };
1737
1768
  }
1738
1769
  }
1770
+ if (app.development.local.port) {
1771
+ additionalConfigOptions.server = {
1772
+ port: app.development.local.port
1773
+ };
1774
+ }
1739
1775
  return {
1740
1776
  name: "vite-plugin-vercel-microfrontends",
1741
1777
  config: () => {