@vercel/microfrontends 1.1.0 → 1.1.1-canary.1

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 (63) hide show
  1. package/dist/bin/cli.cjs +120 -27
  2. package/dist/config.cjs +80 -16
  3. package/dist/config.cjs.map +1 -1
  4. package/dist/config.d.ts +4 -4
  5. package/dist/config.js +80 -16
  6. package/dist/config.js.map +1 -1
  7. package/dist/experimental/sveltekit.cjs +108 -23
  8. package/dist/experimental/sveltekit.cjs.map +1 -1
  9. package/dist/experimental/sveltekit.js +108 -23
  10. package/dist/experimental/sveltekit.js.map +1 -1
  11. package/dist/experimental/vite.cjs +108 -23
  12. package/dist/experimental/vite.cjs.map +1 -1
  13. package/dist/experimental/vite.js +108 -23
  14. package/dist/experimental/vite.js.map +1 -1
  15. package/dist/{index-2b59c627.d.ts → index-7e69650e.d.ts} +11 -5
  16. package/dist/microfrontends/server.cjs +108 -23
  17. package/dist/microfrontends/server.cjs.map +1 -1
  18. package/dist/microfrontends/server.d.ts +4 -4
  19. package/dist/microfrontends/server.js +108 -23
  20. package/dist/microfrontends/server.js.map +1 -1
  21. package/dist/microfrontends.cjs +80 -16
  22. package/dist/microfrontends.cjs.map +1 -1
  23. package/dist/microfrontends.d.ts +4 -4
  24. package/dist/microfrontends.js +80 -16
  25. package/dist/microfrontends.js.map +1 -1
  26. package/dist/next/config.cjs +125 -30
  27. package/dist/next/config.cjs.map +1 -1
  28. package/dist/next/config.js +125 -30
  29. package/dist/next/config.js.map +1 -1
  30. package/dist/next/endpoints.cjs +9 -0
  31. package/dist/next/endpoints.cjs.map +1 -1
  32. package/dist/next/endpoints.d.ts +36 -4
  33. package/dist/next/endpoints.js +8 -0
  34. package/dist/next/endpoints.js.map +1 -1
  35. package/dist/next/middleware.cjs +90 -16
  36. package/dist/next/middleware.cjs.map +1 -1
  37. package/dist/next/middleware.js +90 -16
  38. package/dist/next/middleware.js.map +1 -1
  39. package/dist/next/testing.cjs +84 -21
  40. package/dist/next/testing.cjs.map +1 -1
  41. package/dist/next/testing.d.ts +4 -4
  42. package/dist/next/testing.js +84 -21
  43. package/dist/next/testing.js.map +1 -1
  44. package/dist/overrides.d.ts +3 -3
  45. package/dist/schema.cjs +23 -0
  46. package/dist/schema.cjs.map +1 -1
  47. package/dist/schema.d.ts +7 -1
  48. package/dist/schema.js +13 -0
  49. package/dist/schema.js.map +1 -1
  50. package/dist/{index-2f78c0ca.d.ts → types-6ee19ccc.d.ts} +40 -9
  51. package/dist/{types-b6d38aea.d.ts → types-73527280.d.ts} +1 -1
  52. package/dist/{types-4ef2bddb.d.ts → types-74e3336c.d.ts} +1 -1
  53. package/dist/utils/mfe-port.cjs +108 -23
  54. package/dist/utils/mfe-port.cjs.map +1 -1
  55. package/dist/utils/mfe-port.js +108 -23
  56. package/dist/utils/mfe-port.js.map +1 -1
  57. package/dist/validation.cjs +28 -7
  58. package/dist/validation.cjs.map +1 -1
  59. package/dist/validation.d.ts +1 -1
  60. package/dist/validation.js +28 -7
  61. package/dist/validation.js.map +1 -1
  62. package/package.json +1 -1
  63. package/schema/schema.json +28 -7
package/dist/bin/cli.cjs CHANGED
@@ -29,7 +29,7 @@ var import_commander = require("commander");
29
29
  // package.json
30
30
  var package_default = {
31
31
  name: "@vercel/microfrontends",
32
- version: "1.1.0",
32
+ version: "1.1.1-canary.1",
33
33
  private: false,
34
34
  description: "Defines configuration and utilities for microfrontends development",
35
35
  keywords: [
@@ -418,10 +418,13 @@ var validateConfigPaths = (applicationConfigsById) => {
418
418
  }
419
419
  }
420
420
  if (errors.length) {
421
- throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
422
- type: "config",
423
- subtype: "conflicting_paths"
424
- });
421
+ throw new MicrofrontendError(
422
+ `Invalid paths: ${errors.join(", ")}. See supported paths in the documentation https://vercel.com/docs/microfrontends/path-routing#supported-path-expressions.`,
423
+ {
424
+ type: "config",
425
+ subtype: "conflicting_paths"
426
+ }
427
+ );
425
428
  }
426
429
  };
427
430
  var PATH_DEFAULT_PATTERN = "[^\\/#\\?]+?";
@@ -536,9 +539,40 @@ var validateDeprecatedFields = (config) => {
536
539
  `Application '${applicationId}' cannot contain deprecated field 'production'. Use 'development.fallback' instead.`
537
540
  );
538
541
  }
539
- if (application.development?.local) {
542
+ if (application.development?.localPort) {
543
+ errors.push(
544
+ `Application '${applicationId}' cannot contain deprecated field 'development.localPort'. Use 'developement.local' instead.`
545
+ );
546
+ }
547
+ if (application.development?.fallback && typeof application.development.fallback !== "string") {
548
+ const fallback = application.development.fallback;
549
+ let asString = fallback.host;
550
+ if (fallback.protocol) {
551
+ asString = `${fallback.protocol}://${asString}`;
552
+ }
553
+ if (fallback.port) {
554
+ asString = `${asString}:${fallback.port}`;
555
+ }
540
556
  errors.push(
541
- `Application '${applicationId}' cannot contain deprecated field 'development.local'. Use 'developement.localPort' instead.`
557
+ `Application '${applicationId}' requires a string (not an object) for the 'development.fallback' field. Please set 'development.fallback' to '${asString}'.`
558
+ );
559
+ }
560
+ if (application.development?.local && typeof application.development.local !== "string" && typeof application.development.local !== "number") {
561
+ const local = application.development.local;
562
+ let asString;
563
+ if (local.port && !local.protocol && !local.host) {
564
+ asString = String(local.port);
565
+ } else {
566
+ asString = local.host ?? "localhost";
567
+ if (local.protocol) {
568
+ asString = `${local.protocol}://${asString}`;
569
+ }
570
+ if (local.port) {
571
+ asString = `${asString}:${local.port}`;
572
+ }
573
+ }
574
+ errors.push(
575
+ `Application '${applicationId}' requires a string or number (not an object) for the 'development.local' field. Please set 'development.local' to '${asString}'.`
542
576
  );
543
577
  }
544
578
  }
@@ -602,10 +636,10 @@ var Host = class {
602
636
  }
603
637
  this.local = options?.isLocal;
604
638
  }
605
- static parseUrl(url) {
639
+ static parseUrl(url, defaultProtocol = "https") {
606
640
  let hostToParse = url;
607
641
  if (!/^https?:\/\//.exec(hostToParse)) {
608
- hostToParse = `https://${hostToParse}`;
642
+ hostToParse = `${defaultProtocol}://${hostToParse}`;
609
643
  }
610
644
  const parsed = new URL(hostToParse);
611
645
  if (!parsed.hostname) {
@@ -658,12 +692,39 @@ var LocalHost = class extends Host {
658
692
  constructor({
659
693
  appName,
660
694
  localPort,
661
- ...hostConfig
695
+ local
662
696
  }) {
663
- const host = hostConfig.host ?? "localhost";
664
- const port = localPort ?? hostConfig.port ?? generatePortFromName({ name: appName });
665
- const protocol = hostConfig.protocol ?? "http";
666
- super({ protocol, host, port });
697
+ if (localPort && local) {
698
+ throw new Error(
699
+ `Microfrontends configuration error: '${appName}' has both the 'development.local' and 'development.localPort' fields set. Please remove the 'development.localPort' field and ensure the 'development.local' field has the correct port.`
700
+ );
701
+ }
702
+ let protocol;
703
+ let host;
704
+ let port;
705
+ if (localPort) {
706
+ port = localPort;
707
+ } else if (typeof local === "number") {
708
+ port = local;
709
+ } else if (typeof local === "string") {
710
+ if (/^\d+$/.test(local)) {
711
+ port = Number.parseInt(local);
712
+ } else {
713
+ const parsed = Host.parseUrl(local, "http");
714
+ protocol = parsed.protocol;
715
+ host = parsed.host;
716
+ port = parsed.port;
717
+ }
718
+ } else if (local) {
719
+ protocol = local.protocol;
720
+ host = local.host;
721
+ port = local.port;
722
+ }
723
+ super({
724
+ protocol: protocol ?? "http",
725
+ host: host ?? "localhost",
726
+ port: port ?? generatePortFromName({ name: appName })
727
+ });
667
728
  }
668
729
  };
669
730
 
@@ -679,7 +740,7 @@ var Application = class {
679
740
  local: new LocalHost({
680
741
  appName: name,
681
742
  localPort: app.development?.localPort,
682
- ...app.development?.local
743
+ local: app.development?.local
683
744
  }),
684
745
  fallback: app.development?.fallback ? new Host(app.development.fallback) : void 0
685
746
  };
@@ -689,6 +750,7 @@ var Application = class {
689
750
  this.fallback = new Host(app.production);
690
751
  }
691
752
  this.projectId = app.projectId ?? app.vercel?.projectId;
753
+ this.packageName = app.packageName;
692
754
  this.overrides = overrides?.environment ? {
693
755
  environment: new Host(overrides.environment)
694
756
  } : void 0;
@@ -973,10 +1035,12 @@ var MicrofrontendConfigIsomorphic = class {
973
1035
  ].filter(Boolean);
974
1036
  }
975
1037
  getApplication(name) {
976
- if (this.defaultApplication?.name === name) {
1038
+ if (this.defaultApplication?.name === name || this.defaultApplication?.packageName === name) {
977
1039
  return this.defaultApplication;
978
1040
  }
979
- const app = this.childApplications[name];
1041
+ const app = this.childApplications[name] || Object.values(this.childApplications).find(
1042
+ (child) => child.packageName === name
1043
+ );
980
1044
  if (!app) {
981
1045
  throw new MicrofrontendError(
982
1046
  `Could not find microfrontends configuration for application "${name}"`,
@@ -1487,7 +1551,7 @@ var schema_default = {
1487
1551
  $ref: "#/definitions/Application"
1488
1552
  },
1489
1553
  propertyNames: {
1490
- description: "The unique identifier for a Microfrontend Application. Must match the `name` field of the application's `package.json`."
1554
+ description: "The unique identifier for a Microfrontend Application.\n\nMust match the Vercel project name.\n\nNote: If this name does not also match the name used to run the application, (e.g. the `name` from the `package.json`), then the `packageName` field should be set."
1491
1555
  }
1492
1556
  },
1493
1557
  Application: {
@@ -1509,7 +1573,12 @@ var schema_default = {
1509
1573
  },
1510
1574
  projectId: {
1511
1575
  type: "string",
1512
- description: "Vercel project ID"
1576
+ description: "Vercel project ID, only required if the application name / id is different to the Vercel project name.",
1577
+ deprecated: "Instead, the application id should match the Vercel project name."
1578
+ },
1579
+ packageName: {
1580
+ type: "string",
1581
+ description: "The name used to run the application, e.g. the `name` field in the `package.json`.\n\nThis is used by the local proxy to map the application config to the locally running app.\n\nThis is only necessary when the application name does not match the `name` used in `package.json`."
1513
1582
  },
1514
1583
  production: {
1515
1584
  $ref: "#/definitions/HostConfig",
@@ -1556,12 +1625,23 @@ var schema_default = {
1556
1625
  type: "object",
1557
1626
  properties: {
1558
1627
  local: {
1559
- $ref: "#/definitions/LocalHostConfig",
1560
- deprecated: "This is being replaced by the `localPort` field below."
1628
+ anyOf: [
1629
+ {
1630
+ type: "number"
1631
+ },
1632
+ {
1633
+ type: "string"
1634
+ },
1635
+ {
1636
+ $ref: "#/definitions/LocalHostConfig"
1637
+ }
1638
+ ],
1639
+ description: "A local port number or host string that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTP. If omitted, the port defaults to a unique, but stable (based on the application name) number.\n\nExamples of valid values:\n- 8080\n- my.localhost.me\n- my.localhost.me:8080\n- https://my.localhost.me\n- https://my.localhost.me:8080\n\nPassing a LocalHostConfig is deprecated and will go away soon, please pass a number or string."
1561
1640
  },
1562
1641
  localPort: {
1563
1642
  type: "number",
1564
- description: "The local port number that this application runs on when it is running locally. Common values include `80` for HTTP and `443` for HTTPS."
1643
+ description: "The local port number that this application runs on when it is running locally. Common values include `80` for HTTP and `443` for HTTPS. If omitted, the port defaults to a unique, but stable (based on the application name) number.",
1644
+ deprecated: "Please set the port with the 'local' field instead."
1565
1645
  },
1566
1646
  fallback: {
1567
1647
  anyOf: [
@@ -1572,7 +1652,7 @@ var schema_default = {
1572
1652
  type: "string"
1573
1653
  }
1574
1654
  ],
1575
- description: "Fallback for local development, could be a host config that points to any environment. If this is not provided, or the application is not running - requests to the application in local development will error.\n\nIf passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTPS. If omitted, the port defaults to `80` for HTTP and `443` for HTTPS."
1655
+ description: "Fallback for local development, could point to any environment. If this is not provided, or the application is not running - requests to the application in local development will error.\n\nIf passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTPS. If omitted, the port defaults to `80` for HTTP and `443` for HTTPS.\n\nPassing a HostConfig is deprecated and will go away soon, please pass a string."
1576
1656
  },
1577
1657
  task: {
1578
1658
  type: "string",
@@ -1609,7 +1689,12 @@ var schema_default = {
1609
1689
  },
1610
1690
  projectId: {
1611
1691
  type: "string",
1612
- description: "Vercel project ID"
1692
+ description: "Vercel project ID, only required if the application name / id is different to the Vercel project name.",
1693
+ deprecated: "Instead, the application id should match the Vercel project name."
1694
+ },
1695
+ packageName: {
1696
+ type: "string",
1697
+ description: "The name used to run the application, e.g. the `name` field in the `package.json`.\n\nThis is used by the local proxy to map the application config to the locally running app.\n\nThis is only necessary when the application name does not match the `name` used in `package.json`."
1613
1698
  },
1614
1699
  production: {
1615
1700
  $ref: "#/definitions/HostConfig",
@@ -1949,7 +2034,9 @@ var ProxyRequestRouter = class {
1949
2034
  return this.getApplicationTarget(defaultApp);
1950
2035
  }
1951
2036
  getApplicationTarget(application) {
1952
- const useDev = this.localApps.includes(application.name);
2037
+ const useDev = this.localApps.find(
2038
+ (name) => name === application.name || name === application.packageName
2039
+ );
1953
2040
  let applicationName = application.name;
1954
2041
  let host = useDev ? application.development.local : application.fallback;
1955
2042
  if (application.overrides?.environment?.host) {
@@ -2163,7 +2250,12 @@ var ProxyRequestRouter = class {
2163
2250
  } : null;
2164
2251
  }
2165
2252
  isDefaultAppLocal() {
2166
- return this.localApps.includes(this.config.getDefaultApplication().name);
2253
+ const defaultApp = this.config.getDefaultApplication();
2254
+ return Boolean(
2255
+ this.localApps.find(
2256
+ (name) => name === defaultApp.name || name === defaultApp.packageName
2257
+ )
2258
+ );
2167
2259
  }
2168
2260
  };
2169
2261
  var LocalProxy = class {
@@ -2312,7 +2404,8 @@ function extractMfeFlagValue(path7) {
2312
2404
  function stringAsBoolean(value) {
2313
2405
  if (value === "true") {
2314
2406
  return true;
2315
- } else if (value === "false") {
2407
+ }
2408
+ if (value === "false") {
2316
2409
  return false;
2317
2410
  }
2318
2411
  return void 0;
package/dist/config.cjs CHANGED
@@ -298,10 +298,13 @@ var validateConfigPaths = (applicationConfigsById) => {
298
298
  }
299
299
  }
300
300
  if (errors.length) {
301
- throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
302
- type: "config",
303
- subtype: "conflicting_paths"
304
- });
301
+ throw new MicrofrontendError(
302
+ `Invalid paths: ${errors.join(", ")}. See supported paths in the documentation https://vercel.com/docs/microfrontends/path-routing#supported-path-expressions.`,
303
+ {
304
+ type: "config",
305
+ subtype: "conflicting_paths"
306
+ }
307
+ );
305
308
  }
306
309
  };
307
310
  var PATH_DEFAULT_PATTERN = "[^\\/#\\?]+?";
@@ -416,9 +419,40 @@ var validateDeprecatedFields = (config) => {
416
419
  `Application '${applicationId}' cannot contain deprecated field 'production'. Use 'development.fallback' instead.`
417
420
  );
418
421
  }
419
- if (application.development?.local) {
422
+ if (application.development?.localPort) {
423
+ errors.push(
424
+ `Application '${applicationId}' cannot contain deprecated field 'development.localPort'. Use 'developement.local' instead.`
425
+ );
426
+ }
427
+ if (application.development?.fallback && typeof application.development.fallback !== "string") {
428
+ const fallback = application.development.fallback;
429
+ let asString = fallback.host;
430
+ if (fallback.protocol) {
431
+ asString = `${fallback.protocol}://${asString}`;
432
+ }
433
+ if (fallback.port) {
434
+ asString = `${asString}:${fallback.port}`;
435
+ }
436
+ errors.push(
437
+ `Application '${applicationId}' requires a string (not an object) for the 'development.fallback' field. Please set 'development.fallback' to '${asString}'.`
438
+ );
439
+ }
440
+ if (application.development?.local && typeof application.development.local !== "string" && typeof application.development.local !== "number") {
441
+ const local = application.development.local;
442
+ let asString;
443
+ if (local.port && !local.protocol && !local.host) {
444
+ asString = String(local.port);
445
+ } else {
446
+ asString = local.host ?? "localhost";
447
+ if (local.protocol) {
448
+ asString = `${local.protocol}://${asString}`;
449
+ }
450
+ if (local.port) {
451
+ asString = `${asString}:${local.port}`;
452
+ }
453
+ }
420
454
  errors.push(
421
- `Application '${applicationId}' cannot contain deprecated field 'development.local'. Use 'developement.localPort' instead.`
455
+ `Application '${applicationId}' requires a string or number (not an object) for the 'development.local' field. Please set 'development.local' to '${asString}'.`
422
456
  );
423
457
  }
424
458
  }
@@ -482,10 +516,10 @@ var Host = class {
482
516
  }
483
517
  this.local = options?.isLocal;
484
518
  }
485
- static parseUrl(url) {
519
+ static parseUrl(url, defaultProtocol = "https") {
486
520
  let hostToParse = url;
487
521
  if (!/^https?:\/\//.exec(hostToParse)) {
488
- hostToParse = `https://${hostToParse}`;
522
+ hostToParse = `${defaultProtocol}://${hostToParse}`;
489
523
  }
490
524
  const parsed = new URL(hostToParse);
491
525
  if (!parsed.hostname) {
@@ -538,12 +572,39 @@ var LocalHost = class extends Host {
538
572
  constructor({
539
573
  appName,
540
574
  localPort,
541
- ...hostConfig
575
+ local
542
576
  }) {
543
- const host = hostConfig.host ?? "localhost";
544
- const port = localPort ?? hostConfig.port ?? generatePortFromName({ name: appName });
545
- const protocol = hostConfig.protocol ?? "http";
546
- super({ protocol, host, port });
577
+ if (localPort && local) {
578
+ throw new Error(
579
+ `Microfrontends configuration error: '${appName}' has both the 'development.local' and 'development.localPort' fields set. Please remove the 'development.localPort' field and ensure the 'development.local' field has the correct port.`
580
+ );
581
+ }
582
+ let protocol;
583
+ let host;
584
+ let port;
585
+ if (localPort) {
586
+ port = localPort;
587
+ } else if (typeof local === "number") {
588
+ port = local;
589
+ } else if (typeof local === "string") {
590
+ if (/^\d+$/.test(local)) {
591
+ port = Number.parseInt(local);
592
+ } else {
593
+ const parsed = Host.parseUrl(local, "http");
594
+ protocol = parsed.protocol;
595
+ host = parsed.host;
596
+ port = parsed.port;
597
+ }
598
+ } else if (local) {
599
+ protocol = local.protocol;
600
+ host = local.host;
601
+ port = local.port;
602
+ }
603
+ super({
604
+ protocol: protocol ?? "http",
605
+ host: host ?? "localhost",
606
+ port: port ?? generatePortFromName({ name: appName })
607
+ });
547
608
  }
548
609
  };
549
610
 
@@ -559,7 +620,7 @@ var Application = class {
559
620
  local: new LocalHost({
560
621
  appName: name,
561
622
  localPort: app.development?.localPort,
562
- ...app.development?.local
623
+ local: app.development?.local
563
624
  }),
564
625
  fallback: app.development?.fallback ? new Host(app.development.fallback) : void 0
565
626
  };
@@ -569,6 +630,7 @@ var Application = class {
569
630
  this.fallback = new Host(app.production);
570
631
  }
571
632
  this.projectId = app.projectId ?? app.vercel?.projectId;
633
+ this.packageName = app.packageName;
572
634
  this.overrides = overrides?.environment ? {
573
635
  environment: new Host(overrides.environment)
574
636
  } : void 0;
@@ -734,10 +796,12 @@ var MicrofrontendConfigIsomorphic = class {
734
796
  ].filter(Boolean);
735
797
  }
736
798
  getApplication(name) {
737
- if (this.defaultApplication?.name === name) {
799
+ if (this.defaultApplication?.name === name || this.defaultApplication?.packageName === name) {
738
800
  return this.defaultApplication;
739
801
  }
740
- const app = this.childApplications[name];
802
+ const app = this.childApplications[name] || Object.values(this.childApplications).find(
803
+ (child) => child.packageName === name
804
+ );
741
805
  if (!app) {
742
806
  throw new MicrofrontendError(
743
807
  `Could not find microfrontends configuration for application "${name}"`,