@vercel/microfrontends 2.0.0 → 2.1.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 (46) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +1 -5
  3. package/dist/bin/cli.cjs +226 -79
  4. package/dist/config.cjs +5 -4
  5. package/dist/config.cjs.map +1 -1
  6. package/dist/config.js +5 -4
  7. package/dist/config.js.map +1 -1
  8. package/dist/experimental/sveltekit.cjs +51 -20
  9. package/dist/experimental/sveltekit.cjs.map +1 -1
  10. package/dist/experimental/sveltekit.js +51 -20
  11. package/dist/experimental/sveltekit.js.map +1 -1
  12. package/dist/experimental/vite.cjs +51 -20
  13. package/dist/experimental/vite.cjs.map +1 -1
  14. package/dist/experimental/vite.js +51 -20
  15. package/dist/experimental/vite.js.map +1 -1
  16. package/dist/microfrontends/server.cjs +51 -20
  17. package/dist/microfrontends/server.cjs.map +1 -1
  18. package/dist/microfrontends/server.js +51 -20
  19. package/dist/microfrontends/server.js.map +1 -1
  20. package/dist/microfrontends/utils.cjs +32 -7
  21. package/dist/microfrontends/utils.cjs.map +1 -1
  22. package/dist/microfrontends/utils.d.ts +8 -2
  23. package/dist/microfrontends/utils.js +31 -7
  24. package/dist/microfrontends/utils.js.map +1 -1
  25. package/dist/next/client.cjs +1 -1
  26. package/dist/next/client.cjs.map +1 -1
  27. package/dist/next/client.d.ts +15 -1
  28. package/dist/next/client.js +1 -1
  29. package/dist/next/client.js.map +1 -1
  30. package/dist/next/config.cjs +62 -20
  31. package/dist/next/config.cjs.map +1 -1
  32. package/dist/next/config.js +62 -20
  33. package/dist/next/config.js.map +1 -1
  34. package/dist/next/middleware.cjs +5 -4
  35. package/dist/next/middleware.cjs.map +1 -1
  36. package/dist/next/middleware.js +5 -4
  37. package/dist/next/middleware.js.map +1 -1
  38. package/dist/next/testing.cjs +5 -4
  39. package/dist/next/testing.cjs.map +1 -1
  40. package/dist/next/testing.js +5 -4
  41. package/dist/next/testing.js.map +1 -1
  42. package/dist/utils/mfe-port.cjs +66 -40
  43. package/dist/utils/mfe-port.cjs.map +1 -1
  44. package/dist/utils/mfe-port.js +66 -40
  45. package/dist/utils/mfe-port.js.map +1 -1
  46. package/package.json +4 -4
@@ -191,22 +191,38 @@ import { readFileSync } from "node:fs";
191
191
  import { parse } from "jsonc-parser";
192
192
  import fg from "fast-glob";
193
193
 
194
- // src/config/constants.ts
195
- var CONFIGURATION_FILENAMES = [
194
+ // src/config/microfrontends/utils/get-config-file-name.ts
195
+ var DEFAULT_CONFIGURATION_FILENAMES = [
196
196
  "microfrontends.jsonc",
197
197
  "microfrontends.json"
198
198
  ];
199
+ function getPossibleConfigurationFilenames({
200
+ customConfigFilename
201
+ }) {
202
+ if (customConfigFilename) {
203
+ if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
204
+ throw new Error(
205
+ `The VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable must end with '.json' or '.jsonc'. Received: ${customConfigFilename}`
206
+ );
207
+ }
208
+ return Array.from(
209
+ /* @__PURE__ */ new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES])
210
+ );
211
+ }
212
+ return DEFAULT_CONFIGURATION_FILENAMES;
213
+ }
199
214
 
200
215
  // src/config/microfrontends/utils/infer-microfrontends-location.ts
201
216
  var configCache = {};
202
217
  function findPackageWithMicrofrontendsConfig({
203
218
  repositoryRoot,
204
- applicationContext
219
+ applicationContext,
220
+ customConfigFilename
205
221
  }) {
206
222
  const applicationName = applicationContext.name;
207
223
  try {
208
224
  const microfrontendsJsonPaths = fg.globSync(
209
- `**/{${CONFIGURATION_FILENAMES.join(",")}}`,
225
+ `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
210
226
  {
211
227
  cwd: repositoryRoot,
212
228
  absolute: true,
@@ -262,6 +278,8 @@ Names of applications in \`microfrontends.json\` must match the Vercel Project n
262
278
 
263
279
  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.
264
280
 
281
+ If your Vercel Microfrontends configuration has a custom name, ensure the VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable is set, you can pull the vercel project environment variables using the "vercel env pull" command.
282
+
265
283
  If you suspect this is thrown in error, please reach out to the Vercel team.`,
266
284
  { type: "config", subtype: "inference_failed" }
267
285
  );
@@ -276,7 +294,7 @@ If you suspect this is thrown in error, please reach out to the Vercel team.`,
276
294
  }
277
295
  }
278
296
  function inferMicrofrontendsLocation(opts) {
279
- const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}`;
297
+ const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ""}`;
280
298
  if (configCache[cacheKey]) {
281
299
  return configCache[cacheKey];
282
300
  }
@@ -342,8 +360,13 @@ function findPackageRoot(startDir) {
342
360
  // src/config/microfrontends/utils/find-config.ts
343
361
  import fs4 from "node:fs";
344
362
  import { join } from "node:path";
345
- function findConfig({ dir }) {
346
- for (const filename of CONFIGURATION_FILENAMES) {
363
+ function findConfig({
364
+ dir,
365
+ customConfigFilename
366
+ }) {
367
+ for (const filename of getPossibleConfigurationFilenames({
368
+ customConfigFilename
369
+ })) {
347
370
  const maybeConfig = join(dir, filename);
348
371
  if (fs4.existsSync(maybeConfig)) {
349
372
  return maybeConfig;
@@ -410,7 +433,7 @@ var MicrofrontendConfigClient = class {
410
433
  static fromEnv(config) {
411
434
  if (!config) {
412
435
  throw new Error(
413
- "Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
436
+ "Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`? Is the local proxy running and this application is being accessed via the proxy port? See https://vercel.com/docs/microfrontends/local-development#setting-up-microfrontends-proxy"
414
437
  );
415
438
  }
416
439
  return new MicrofrontendConfigClient(JSON.parse(config));
@@ -550,10 +573,11 @@ function validatePathExpression(path7) {
550
573
  }
551
574
  if (token.pattern !== PATH_DEFAULT_PATTERN && // Allows (a|b|c) and ((?!a|b|c).*) regex
552
575
  // Only limited regex is supported for now, due to performance considerations
553
- !/^(?<allowed>[\w]+(?:\|[^:|()]+)+)$|^\(\?!(?<disallowed>[\w]+(?:\|[^:|()]+)*)\)\.\*$/.test(
554
- token.pattern
576
+ // Allows all letters, numbers, and hyphens. Other characters must be escaped.
577
+ !/^(?<allowed>[\w-~]+(?:\|[^:|()]+)+)$|^\(\?!(?<disallowed>[\w-~]+(?:\|[^:|()]+)*)\)\.\*$/.test(
578
+ token.pattern.replace(/\\./g, "")
555
579
  )) {
556
- return `Path ${path7} cannot use unsupported regular expression wildcard`;
580
+ return `Path ${path7} cannot use unsupported regular expression wildcard. If the path includes special characters, they must be escaped with backslash (e.g. '\\(')`;
557
581
  }
558
582
  if (token.modifier && i !== tokens.length - 1) {
559
583
  return `Modifier ${token.modifier} is not allowed on wildcard :${token.name} in ${path7}. Modifiers are only allowed in the last path component`;
@@ -1445,7 +1469,11 @@ var MicrofrontendsServer = class {
1445
1469
  appName,
1446
1470
  packageRoot
1447
1471
  });
1448
- const maybeConfig = findConfig({ dir: packageRoot });
1472
+ const customConfigFilename = process.env.VC_MICROFRONTENDS_CONFIG_FILE_NAME;
1473
+ const maybeConfig = findConfig({
1474
+ dir: packageRoot,
1475
+ customConfigFilename
1476
+ });
1449
1477
  if (maybeConfig) {
1450
1478
  return MicrofrontendsServer.fromFile({
1451
1479
  filePath: maybeConfig,
@@ -1454,11 +1482,9 @@ var MicrofrontendsServer = class {
1454
1482
  }
1455
1483
  const repositoryRoot = findRepositoryRoot();
1456
1484
  const isMonorepo2 = isMonorepo({ repositoryRoot });
1457
- if (typeof process.env.VC_MICROFRONTENDS_CONFIG === "string") {
1458
- const maybeConfigFromEnv = resolve(
1459
- packageRoot,
1460
- process.env.VC_MICROFRONTENDS_CONFIG
1461
- );
1485
+ const configFromEnv = process.env.VC_MICROFRONTENDS_CONFIG;
1486
+ if (typeof configFromEnv === "string") {
1487
+ const maybeConfigFromEnv = resolve(packageRoot, configFromEnv);
1462
1488
  if (maybeConfigFromEnv) {
1463
1489
  return MicrofrontendsServer.fromFile({
1464
1490
  filePath: maybeConfigFromEnv,
@@ -1467,7 +1493,8 @@ var MicrofrontendsServer = class {
1467
1493
  }
1468
1494
  } else {
1469
1495
  const maybeConfigFromVercel = findConfig({
1470
- dir: join2(packageRoot, ".vercel")
1496
+ dir: join2(packageRoot, ".vercel"),
1497
+ customConfigFilename
1471
1498
  });
1472
1499
  if (maybeConfigFromVercel) {
1473
1500
  return MicrofrontendsServer.fromFile({
@@ -1478,9 +1505,13 @@ var MicrofrontendsServer = class {
1478
1505
  if (isMonorepo2) {
1479
1506
  const defaultPackage = inferMicrofrontendsLocation({
1480
1507
  repositoryRoot,
1481
- applicationContext
1508
+ applicationContext,
1509
+ customConfigFilename
1510
+ });
1511
+ const maybeConfigFromDefault = findConfig({
1512
+ dir: defaultPackage,
1513
+ customConfigFilename
1482
1514
  });
1483
- const maybeConfigFromDefault = findConfig({ dir: defaultPackage });
1484
1515
  if (maybeConfigFromDefault) {
1485
1516
  return MicrofrontendsServer.fromFile({
1486
1517
  filePath: maybeConfigFromDefault,
@@ -1556,19 +1587,19 @@ var MicrofrontendsServer = class {
1556
1587
  // src/utils/mfe-port.ts
1557
1588
  function mfePort(packageDir) {
1558
1589
  const { name: appName, version } = getPackageJson(packageDir);
1559
- const result = loadConfig({ packageDir, appName });
1560
- if (!result) {
1561
- throw new MicrofrontendError(
1562
- `Unable to determine configured port for ${appName}`,
1563
- { type: "config", subtype: "not_found" }
1564
- );
1590
+ try {
1591
+ const result = loadConfig({ packageDir, appName });
1592
+ const { port } = result;
1593
+ return {
1594
+ name: appName,
1595
+ version,
1596
+ port
1597
+ };
1598
+ } catch (e) {
1599
+ throw new Error(`Unable to determine configured port for ${appName}`, {
1600
+ cause: e
1601
+ });
1565
1602
  }
1566
- const { port } = result;
1567
- return {
1568
- name: appName,
1569
- version,
1570
- port
1571
- };
1572
1603
  }
1573
1604
  function getPackageJson(packageDir) {
1574
1605
  const filePath = path6.join(packageDir, "package.json");
@@ -1578,14 +1609,9 @@ function loadConfig({
1578
1609
  packageDir,
1579
1610
  appName
1580
1611
  }) {
1581
- let config;
1582
- try {
1583
- config = MicrofrontendsServer.infer({
1584
- directory: packageDir
1585
- });
1586
- } catch (e) {
1587
- return void 0;
1588
- }
1612
+ const config = MicrofrontendsServer.infer({
1613
+ directory: packageDir
1614
+ });
1589
1615
  const app = config.config.getApplication(appName);
1590
1616
  const port = app.development.local.port ?? (app.development.local.protocol === "https" ? 443 : 80);
1591
1617
  return { port };