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