@vercel/microfrontends 1.1.1-canary.2 → 1.1.1-canary.3

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 (47) hide show
  1. package/dist/bin/cli.cjs +79 -20
  2. package/dist/config.cjs +16 -9
  3. package/dist/config.cjs.map +1 -1
  4. package/dist/config.js +16 -9
  5. package/dist/config.js.map +1 -1
  6. package/dist/experimental/sveltekit.cjs +77 -18
  7. package/dist/experimental/sveltekit.cjs.map +1 -1
  8. package/dist/experimental/sveltekit.js +77 -18
  9. package/dist/experimental/sveltekit.js.map +1 -1
  10. package/dist/experimental/vite.cjs +77 -18
  11. package/dist/experimental/vite.cjs.map +1 -1
  12. package/dist/experimental/vite.js +77 -18
  13. package/dist/experimental/vite.js.map +1 -1
  14. package/dist/microfrontends/server.cjs +77 -18
  15. package/dist/microfrontends/server.cjs.map +1 -1
  16. package/dist/microfrontends/server.js +77 -18
  17. package/dist/microfrontends/server.js.map +1 -1
  18. package/dist/microfrontends.cjs +16 -9
  19. package/dist/microfrontends.cjs.map +1 -1
  20. package/dist/microfrontends.js +16 -9
  21. package/dist/microfrontends.js.map +1 -1
  22. package/dist/next/config.cjs +77 -18
  23. package/dist/next/config.cjs.map +1 -1
  24. package/dist/next/config.js +77 -18
  25. package/dist/next/config.js.map +1 -1
  26. package/dist/next/endpoints.cjs +2 -0
  27. package/dist/next/endpoints.cjs.map +1 -1
  28. package/dist/next/endpoints.d.ts +11 -1
  29. package/dist/next/endpoints.js +1 -0
  30. package/dist/next/endpoints.js.map +1 -1
  31. package/dist/next/middleware.cjs +16 -9
  32. package/dist/next/middleware.cjs.map +1 -1
  33. package/dist/next/middleware.js +16 -9
  34. package/dist/next/middleware.js.map +1 -1
  35. package/dist/next/testing.cjs +16 -9
  36. package/dist/next/testing.cjs.map +1 -1
  37. package/dist/next/testing.js +16 -9
  38. package/dist/next/testing.js.map +1 -1
  39. package/dist/utils/mfe-port.cjs +77 -18
  40. package/dist/utils/mfe-port.cjs.map +1 -1
  41. package/dist/utils/mfe-port.js +77 -18
  42. package/dist/utils/mfe-port.js.map +1 -1
  43. package/dist/validation.cjs +49 -6
  44. package/dist/validation.cjs.map +1 -1
  45. package/dist/validation.js +49 -6
  46. package/dist/validation.js.map +1 -1
  47. package/package.json +2 -2
@@ -229,6 +229,10 @@ var MicrofrontendConfigClient = class {
229
229
 
230
230
  // src/config/microfrontends-config/isomorphic/validation.ts
231
231
  import { pathToRegexp as pathToRegexp2, parse as parsePathRegexp } from "path-to-regexp";
232
+ var LIST_FORMATTER = new Intl.ListFormat("en", {
233
+ style: "long",
234
+ type: "conjunction"
235
+ });
232
236
  var validateConfigPaths = (applicationConfigsById) => {
233
237
  if (!applicationConfigsById) {
234
238
  return;
@@ -361,15 +365,15 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
361
365
  if (!applicationConfigsById) {
362
366
  return;
363
367
  }
364
- const applicationsWithRouting = Object.entries(applicationConfigsById).filter(
365
- ([, app]) => !isDefaultApp(app)
366
- );
367
- const applicationsWithRoutingNames = applicationsWithRouting.map(
368
- ([key]) => key
368
+ const applicationsWithoutRouting = Object.entries(
369
+ applicationConfigsById
370
+ ).filter(([, app]) => isDefaultApp(app));
371
+ const numApplicationsWithoutRouting = applicationsWithoutRouting.reduce(
372
+ (acc) => {
373
+ return acc + 1;
374
+ },
375
+ 0
369
376
  );
370
- const numApplications = Object.keys(applicationConfigsById).length;
371
- const numApplicationsWithRouting = applicationsWithRoutingNames.length;
372
- const numApplicationsWithoutRouting = numApplications - numApplicationsWithRouting;
373
377
  if (numApplicationsWithoutRouting === 0) {
374
378
  throw new MicrofrontendError(
375
379
  "No default application found. At least one application needs to be the default by omitting routing.",
@@ -377,8 +381,11 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
377
381
  );
378
382
  }
379
383
  if (numApplicationsWithoutRouting > 1) {
384
+ const applicationNamesMissingRouting = applicationsWithoutRouting.map(
385
+ ([name]) => name
386
+ );
380
387
  throw new MicrofrontendError(
381
- `Only one application can omit "routing". Found ${applicationsWithRoutingNames.length - Object.keys(applicationConfigsById).length > 1}.`,
388
+ `All applications except for the default app must contain the "routing" field. Applications that are missing routing: ${LIST_FORMATTER.format(applicationNamesMissingRouting)}.`,
382
389
  { type: "config", subtype: "multiple_default_applications" }
383
390
  );
384
391
  }
@@ -947,14 +954,20 @@ var Microfrontends = class {
947
954
  import fs from "node:fs";
948
955
  import path from "node:path";
949
956
  var GIT_DIRECTORY = ".git";
957
+ function hasGitDirectory(dir) {
958
+ const gitPath = path.join(dir, GIT_DIRECTORY);
959
+ return fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory();
960
+ }
961
+ function hasPnpmWorkspaces(dir) {
962
+ return fs.existsSync(path.join(dir, "pnpm-workspace.yaml"));
963
+ }
950
964
  function findRepositoryRoot(startDir) {
951
965
  if (process.env.NX_WORKSPACE_ROOT) {
952
966
  return process.env.NX_WORKSPACE_ROOT;
953
967
  }
954
968
  let currentDir = startDir || process.cwd();
955
969
  while (currentDir !== path.parse(currentDir).root) {
956
- const gitPath = path.join(currentDir, GIT_DIRECTORY);
957
- if (fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory()) {
970
+ if (hasGitDirectory(currentDir) || hasPnpmWorkspaces(currentDir)) {
958
971
  return currentDir;
959
972
  }
960
973
  currentDir = path.dirname(currentDir);
@@ -1065,7 +1078,7 @@ function findDefaultMicrofrontendsPackages({
1065
1078
  }
1066
1079
  if (matchingPaths.length > 1) {
1067
1080
  throw new Error(
1068
- `Found multiple default applications referencing "${applicationName}" in the repository, this is not yet supported.
1081
+ `Found multiple default applications referencing "${applicationName}" in the repository, but only one is allowed.
1069
1082
  ${matchingPaths.join("\n \u2022 ")}`
1070
1083
  );
1071
1084
  }
@@ -1507,13 +1520,54 @@ var schema_default = {
1507
1520
  var SCHEMA = schema_default;
1508
1521
 
1509
1522
  // src/config/microfrontends/server/validation.ts
1510
- function filterAjvErrors(errors) {
1523
+ var LIST_FORMATTER2 = new Intl.ListFormat("en", {
1524
+ style: "long",
1525
+ type: "disjunction"
1526
+ });
1527
+ function formatAjvErrors(errors) {
1511
1528
  if (!errors) {
1512
1529
  return [];
1513
1530
  }
1514
- return errors.filter((error) => {
1515
- return error.keyword === "additionalProperties" || error.keyword === "required";
1516
- });
1531
+ const errorMessages = [];
1532
+ for (const error of errors) {
1533
+ if (error.instancePath === "" && (error.keyword === "anyOf" || error.keyword === "required" && error.params.missingProperty === "partOf")) {
1534
+ continue;
1535
+ }
1536
+ const instancePath = error.instancePath.slice(1);
1537
+ const formattedInstancePath = instancePath === "" ? "at the root" : `in field ${instancePath}`;
1538
+ if (error.keyword === "required" && error.params.missingProperty === "routing" && instancePath.split("/").length === 2) {
1539
+ errorMessages.push(
1540
+ `Unable to infer if ${instancePath} is the default app or a child app. This usually means that there is another error in the configuration.`
1541
+ );
1542
+ } else if (error.keyword === "anyOf" && instancePath.split("/").length > 2) {
1543
+ const anyOfErrors = errors.filter(
1544
+ (e) => e.instancePath === error.instancePath && e.keyword !== "anyOf"
1545
+ );
1546
+ if (anyOfErrors.every((e) => e.keyword === "type")) {
1547
+ const allowedTypes = LIST_FORMATTER2.format(
1548
+ anyOfErrors.map((e) => {
1549
+ return e.keyword === "type" ? String(e.params.type) : "unknown";
1550
+ })
1551
+ );
1552
+ errorMessages.push(
1553
+ `Incorrect type for ${instancePath}. Must be one of ${allowedTypes}`
1554
+ );
1555
+ } else {
1556
+ errorMessages.push(
1557
+ `Invalid field for ${instancePath}. Possible error messages are ${LIST_FORMATTER2.format(anyOfErrors.map((e) => e.message ?? ""))}`
1558
+ );
1559
+ }
1560
+ } else if (error.keyword === "additionalProperties" && !(error.params.additionalProperty === "routing" && instancePath.split("/").length === 2)) {
1561
+ errorMessages.push(
1562
+ `Property '${error.params.additionalProperty}' is not allowed ${formattedInstancePath}`
1563
+ );
1564
+ } else if (error.keyword === "required") {
1565
+ errorMessages.push(
1566
+ `Property '${error.params.missingProperty}' is required ${formattedInstancePath}`
1567
+ );
1568
+ }
1569
+ }
1570
+ return errorMessages;
1517
1571
  }
1518
1572
  function validateSchema(configString) {
1519
1573
  const parsedConfig = parse3(configString);
@@ -1522,8 +1576,10 @@ function validateSchema(configString) {
1522
1576
  const isValid = validate(parsedConfig);
1523
1577
  if (!isValid) {
1524
1578
  throw new MicrofrontendError(
1525
- `Invalid microfrontends config:
1526
- - ${ajv.errorsText(filterAjvErrors(validate.errors), { separator: "\n - " })}
1579
+ `Invalid microfrontends config:${formatAjvErrors(validate.errors).map((error) => `
1580
+ - ${error}`).join(
1581
+ ""
1582
+ )}
1527
1583
 
1528
1584
  See https://openapi.vercel.sh/microfrontends.json for the schema.`,
1529
1585
  { type: "config", subtype: "does_not_match_schema" }
@@ -1658,6 +1714,9 @@ var MicrofrontendsServer = class extends Microfrontends {
1658
1714
  }
1659
1715
  throw new Error("Unable to infer");
1660
1716
  } catch (e) {
1717
+ if (e instanceof MicrofrontendError) {
1718
+ throw e;
1719
+ }
1661
1720
  throw new MicrofrontendError(
1662
1721
  "Unable to locate and parse microfrontends configuration",
1663
1722
  { cause: e, type: "config", subtype: "inference_failed" }