@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
@@ -220,6 +220,10 @@ var MicrofrontendConfigClient = class {
220
220
 
221
221
  // src/config/microfrontends-config/isomorphic/validation.ts
222
222
  import { pathToRegexp as pathToRegexp2, parse as parsePathRegexp } from "path-to-regexp";
223
+ var LIST_FORMATTER = new Intl.ListFormat("en", {
224
+ style: "long",
225
+ type: "conjunction"
226
+ });
223
227
  var validateConfigPaths = (applicationConfigsById) => {
224
228
  if (!applicationConfigsById) {
225
229
  return;
@@ -352,15 +356,15 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
352
356
  if (!applicationConfigsById) {
353
357
  return;
354
358
  }
355
- const applicationsWithRouting = Object.entries(applicationConfigsById).filter(
356
- ([, app]) => !isDefaultApp(app)
357
- );
358
- const applicationsWithRoutingNames = applicationsWithRouting.map(
359
- ([key]) => key
359
+ const applicationsWithoutRouting = Object.entries(
360
+ applicationConfigsById
361
+ ).filter(([, app]) => isDefaultApp(app));
362
+ const numApplicationsWithoutRouting = applicationsWithoutRouting.reduce(
363
+ (acc) => {
364
+ return acc + 1;
365
+ },
366
+ 0
360
367
  );
361
- const numApplications = Object.keys(applicationConfigsById).length;
362
- const numApplicationsWithRouting = applicationsWithRoutingNames.length;
363
- const numApplicationsWithoutRouting = numApplications - numApplicationsWithRouting;
364
368
  if (numApplicationsWithoutRouting === 0) {
365
369
  throw new MicrofrontendError(
366
370
  "No default application found. At least one application needs to be the default by omitting routing.",
@@ -368,8 +372,11 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
368
372
  );
369
373
  }
370
374
  if (numApplicationsWithoutRouting > 1) {
375
+ const applicationNamesMissingRouting = applicationsWithoutRouting.map(
376
+ ([name]) => name
377
+ );
371
378
  throw new MicrofrontendError(
372
- `Only one application can omit "routing". Found ${applicationsWithRoutingNames.length - Object.keys(applicationConfigsById).length > 1}.`,
379
+ `All applications except for the default app must contain the "routing" field. Applications that are missing routing: ${LIST_FORMATTER.format(applicationNamesMissingRouting)}.`,
373
380
  { type: "config", subtype: "multiple_default_applications" }
374
381
  );
375
382
  }
@@ -938,14 +945,20 @@ var Microfrontends = class {
938
945
  import fs from "node:fs";
939
946
  import path from "node:path";
940
947
  var GIT_DIRECTORY = ".git";
948
+ function hasGitDirectory(dir) {
949
+ const gitPath = path.join(dir, GIT_DIRECTORY);
950
+ return fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory();
951
+ }
952
+ function hasPnpmWorkspaces(dir) {
953
+ return fs.existsSync(path.join(dir, "pnpm-workspace.yaml"));
954
+ }
941
955
  function findRepositoryRoot(startDir) {
942
956
  if (process.env.NX_WORKSPACE_ROOT) {
943
957
  return process.env.NX_WORKSPACE_ROOT;
944
958
  }
945
959
  let currentDir = startDir || process.cwd();
946
960
  while (currentDir !== path.parse(currentDir).root) {
947
- const gitPath = path.join(currentDir, GIT_DIRECTORY);
948
- if (fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory()) {
961
+ if (hasGitDirectory(currentDir) || hasPnpmWorkspaces(currentDir)) {
949
962
  return currentDir;
950
963
  }
951
964
  currentDir = path.dirname(currentDir);
@@ -1056,7 +1069,7 @@ function findDefaultMicrofrontendsPackages({
1056
1069
  }
1057
1070
  if (matchingPaths.length > 1) {
1058
1071
  throw new Error(
1059
- `Found multiple default applications referencing "${applicationName}" in the repository, this is not yet supported.
1072
+ `Found multiple default applications referencing "${applicationName}" in the repository, but only one is allowed.
1060
1073
  ${matchingPaths.join("\n \u2022 ")}`
1061
1074
  );
1062
1075
  }
@@ -1498,13 +1511,54 @@ var schema_default = {
1498
1511
  var SCHEMA = schema_default;
1499
1512
 
1500
1513
  // src/config/microfrontends/server/validation.ts
1501
- function filterAjvErrors(errors) {
1514
+ var LIST_FORMATTER2 = new Intl.ListFormat("en", {
1515
+ style: "long",
1516
+ type: "disjunction"
1517
+ });
1518
+ function formatAjvErrors(errors) {
1502
1519
  if (!errors) {
1503
1520
  return [];
1504
1521
  }
1505
- return errors.filter((error) => {
1506
- return error.keyword === "additionalProperties" || error.keyword === "required";
1507
- });
1522
+ const errorMessages = [];
1523
+ for (const error of errors) {
1524
+ if (error.instancePath === "" && (error.keyword === "anyOf" || error.keyword === "required" && error.params.missingProperty === "partOf")) {
1525
+ continue;
1526
+ }
1527
+ const instancePath = error.instancePath.slice(1);
1528
+ const formattedInstancePath = instancePath === "" ? "at the root" : `in field ${instancePath}`;
1529
+ if (error.keyword === "required" && error.params.missingProperty === "routing" && instancePath.split("/").length === 2) {
1530
+ errorMessages.push(
1531
+ `Unable to infer if ${instancePath} is the default app or a child app. This usually means that there is another error in the configuration.`
1532
+ );
1533
+ } else if (error.keyword === "anyOf" && instancePath.split("/").length > 2) {
1534
+ const anyOfErrors = errors.filter(
1535
+ (e) => e.instancePath === error.instancePath && e.keyword !== "anyOf"
1536
+ );
1537
+ if (anyOfErrors.every((e) => e.keyword === "type")) {
1538
+ const allowedTypes = LIST_FORMATTER2.format(
1539
+ anyOfErrors.map((e) => {
1540
+ return e.keyword === "type" ? String(e.params.type) : "unknown";
1541
+ })
1542
+ );
1543
+ errorMessages.push(
1544
+ `Incorrect type for ${instancePath}. Must be one of ${allowedTypes}`
1545
+ );
1546
+ } else {
1547
+ errorMessages.push(
1548
+ `Invalid field for ${instancePath}. Possible error messages are ${LIST_FORMATTER2.format(anyOfErrors.map((e) => e.message ?? ""))}`
1549
+ );
1550
+ }
1551
+ } else if (error.keyword === "additionalProperties" && !(error.params.additionalProperty === "routing" && instancePath.split("/").length === 2)) {
1552
+ errorMessages.push(
1553
+ `Property '${error.params.additionalProperty}' is not allowed ${formattedInstancePath}`
1554
+ );
1555
+ } else if (error.keyword === "required") {
1556
+ errorMessages.push(
1557
+ `Property '${error.params.missingProperty}' is required ${formattedInstancePath}`
1558
+ );
1559
+ }
1560
+ }
1561
+ return errorMessages;
1508
1562
  }
1509
1563
  function validateSchema(configString) {
1510
1564
  const parsedConfig = parse3(configString);
@@ -1513,8 +1567,10 @@ function validateSchema(configString) {
1513
1567
  const isValid = validate(parsedConfig);
1514
1568
  if (!isValid) {
1515
1569
  throw new MicrofrontendError(
1516
- `Invalid microfrontends config:
1517
- - ${ajv.errorsText(filterAjvErrors(validate.errors), { separator: "\n - " })}
1570
+ `Invalid microfrontends config:${formatAjvErrors(validate.errors).map((error) => `
1571
+ - ${error}`).join(
1572
+ ""
1573
+ )}
1518
1574
 
1519
1575
  See https://openapi.vercel.sh/microfrontends.json for the schema.`,
1520
1576
  { type: "config", subtype: "does_not_match_schema" }
@@ -1649,6 +1705,9 @@ var MicrofrontendsServer = class extends Microfrontends {
1649
1705
  }
1650
1706
  throw new Error("Unable to infer");
1651
1707
  } catch (e) {
1708
+ if (e instanceof MicrofrontendError) {
1709
+ throw e;
1710
+ }
1652
1711
  throw new MicrofrontendError(
1653
1712
  "Unable to locate and parse microfrontends configuration",
1654
1713
  { cause: e, type: "config", subtype: "inference_failed" }