@vercel/microfrontends 1.1.0 → 1.1.1-canary.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 (59) 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.d.ts +2 -2
  31. package/dist/next/middleware.cjs +90 -16
  32. package/dist/next/middleware.cjs.map +1 -1
  33. package/dist/next/middleware.js +90 -16
  34. package/dist/next/middleware.js.map +1 -1
  35. package/dist/next/testing.cjs +84 -21
  36. package/dist/next/testing.cjs.map +1 -1
  37. package/dist/next/testing.d.ts +4 -4
  38. package/dist/next/testing.js +84 -21
  39. package/dist/next/testing.js.map +1 -1
  40. package/dist/overrides.d.ts +3 -3
  41. package/dist/schema.cjs +23 -0
  42. package/dist/schema.cjs.map +1 -1
  43. package/dist/schema.d.ts +7 -1
  44. package/dist/schema.js +13 -0
  45. package/dist/schema.js.map +1 -1
  46. package/dist/{index-2f78c0ca.d.ts → types-6ee19ccc.d.ts} +40 -9
  47. package/dist/{types-b6d38aea.d.ts → types-73527280.d.ts} +1 -1
  48. package/dist/{types-4ef2bddb.d.ts → types-74e3336c.d.ts} +1 -1
  49. package/dist/utils/mfe-port.cjs +108 -23
  50. package/dist/utils/mfe-port.cjs.map +1 -1
  51. package/dist/utils/mfe-port.js +108 -23
  52. package/dist/utils/mfe-port.js.map +1 -1
  53. package/dist/validation.cjs +28 -7
  54. package/dist/validation.cjs.map +1 -1
  55. package/dist/validation.d.ts +1 -1
  56. package/dist/validation.js +28 -7
  57. package/dist/validation.js.map +1 -1
  58. package/package.json +1 -1
  59. package/schema/schema.json +28 -7
@@ -287,10 +287,13 @@ var validateConfigPaths = (applicationConfigsById) => {
287
287
  }
288
288
  }
289
289
  if (errors.length) {
290
- throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
291
- type: "config",
292
- subtype: "conflicting_paths"
293
- });
290
+ throw new MicrofrontendError(
291
+ `Invalid paths: ${errors.join(", ")}. See supported paths in the documentation https://vercel.com/docs/microfrontends/path-routing#supported-path-expressions.`,
292
+ {
293
+ type: "config",
294
+ subtype: "conflicting_paths"
295
+ }
296
+ );
294
297
  }
295
298
  };
296
299
  var PATH_DEFAULT_PATTERN = "[^\\/#\\?]+?";
@@ -405,9 +408,40 @@ var validateDeprecatedFields = (config) => {
405
408
  `Application '${applicationId}' cannot contain deprecated field 'production'. Use 'development.fallback' instead.`
406
409
  );
407
410
  }
408
- if (application.development?.local) {
411
+ if (application.development?.localPort) {
412
+ errors.push(
413
+ `Application '${applicationId}' cannot contain deprecated field 'development.localPort'. Use 'developement.local' instead.`
414
+ );
415
+ }
416
+ if (application.development?.fallback && typeof application.development.fallback !== "string") {
417
+ const fallback = application.development.fallback;
418
+ let asString = fallback.host;
419
+ if (fallback.protocol) {
420
+ asString = `${fallback.protocol}://${asString}`;
421
+ }
422
+ if (fallback.port) {
423
+ asString = `${asString}:${fallback.port}`;
424
+ }
425
+ errors.push(
426
+ `Application '${applicationId}' requires a string (not an object) for the 'development.fallback' field. Please set 'development.fallback' to '${asString}'.`
427
+ );
428
+ }
429
+ if (application.development?.local && typeof application.development.local !== "string" && typeof application.development.local !== "number") {
430
+ const local = application.development.local;
431
+ let asString;
432
+ if (local.port && !local.protocol && !local.host) {
433
+ asString = String(local.port);
434
+ } else {
435
+ asString = local.host ?? "localhost";
436
+ if (local.protocol) {
437
+ asString = `${local.protocol}://${asString}`;
438
+ }
439
+ if (local.port) {
440
+ asString = `${asString}:${local.port}`;
441
+ }
442
+ }
409
443
  errors.push(
410
- `Application '${applicationId}' cannot contain deprecated field 'development.local'. Use 'developement.localPort' instead.`
444
+ `Application '${applicationId}' requires a string or number (not an object) for the 'development.local' field. Please set 'development.local' to '${asString}'.`
411
445
  );
412
446
  }
413
447
  }
@@ -471,10 +505,10 @@ var Host = class {
471
505
  }
472
506
  this.local = options?.isLocal;
473
507
  }
474
- static parseUrl(url) {
508
+ static parseUrl(url, defaultProtocol = "https") {
475
509
  let hostToParse = url;
476
510
  if (!/^https?:\/\//.exec(hostToParse)) {
477
- hostToParse = `https://${hostToParse}`;
511
+ hostToParse = `${defaultProtocol}://${hostToParse}`;
478
512
  }
479
513
  const parsed = new URL(hostToParse);
480
514
  if (!parsed.hostname) {
@@ -527,12 +561,39 @@ var LocalHost = class extends Host {
527
561
  constructor({
528
562
  appName,
529
563
  localPort,
530
- ...hostConfig
564
+ local
531
565
  }) {
532
- const host = hostConfig.host ?? "localhost";
533
- const port = localPort ?? hostConfig.port ?? generatePortFromName({ name: appName });
534
- const protocol = hostConfig.protocol ?? "http";
535
- super({ protocol, host, port });
566
+ if (localPort && local) {
567
+ throw new Error(
568
+ `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.`
569
+ );
570
+ }
571
+ let protocol;
572
+ let host;
573
+ let port;
574
+ if (localPort) {
575
+ port = localPort;
576
+ } else if (typeof local === "number") {
577
+ port = local;
578
+ } else if (typeof local === "string") {
579
+ if (/^\d+$/.test(local)) {
580
+ port = Number.parseInt(local);
581
+ } else {
582
+ const parsed = Host.parseUrl(local, "http");
583
+ protocol = parsed.protocol;
584
+ host = parsed.host;
585
+ port = parsed.port;
586
+ }
587
+ } else if (local) {
588
+ protocol = local.protocol;
589
+ host = local.host;
590
+ port = local.port;
591
+ }
592
+ super({
593
+ protocol: protocol ?? "http",
594
+ host: host ?? "localhost",
595
+ port: port ?? generatePortFromName({ name: appName })
596
+ });
536
597
  }
537
598
  };
538
599
 
@@ -548,7 +609,7 @@ var Application = class {
548
609
  local: new LocalHost({
549
610
  appName: name,
550
611
  localPort: app.development?.localPort,
551
- ...app.development?.local
612
+ local: app.development?.local
552
613
  }),
553
614
  fallback: app.development?.fallback ? new Host(app.development.fallback) : void 0
554
615
  };
@@ -558,6 +619,7 @@ var Application = class {
558
619
  this.fallback = new Host(app.production);
559
620
  }
560
621
  this.projectId = app.projectId ?? app.vercel?.projectId;
622
+ this.packageName = app.packageName;
561
623
  this.overrides = overrides?.environment ? {
562
624
  environment: new Host(overrides.environment)
563
625
  } : void 0;
@@ -723,10 +785,12 @@ var MicrofrontendConfigIsomorphic = class {
723
785
  ].filter(Boolean);
724
786
  }
725
787
  getApplication(name) {
726
- if (this.defaultApplication?.name === name) {
788
+ if (this.defaultApplication?.name === name || this.defaultApplication?.packageName === name) {
727
789
  return this.defaultApplication;
728
790
  }
729
- const app = this.childApplications[name];
791
+ const app = this.childApplications[name] || Object.values(this.childApplications).find(
792
+ (child) => child.packageName === name
793
+ );
730
794
  if (!app) {
731
795
  throw new MicrofrontendError(
732
796
  `Could not find microfrontends configuration for application "${name}"`,
@@ -1228,7 +1292,7 @@ var schema_default = {
1228
1292
  $ref: "#/definitions/Application"
1229
1293
  },
1230
1294
  propertyNames: {
1231
- description: "The unique identifier for a Microfrontend Application. Must match the `name` field of the application's `package.json`."
1295
+ 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."
1232
1296
  }
1233
1297
  },
1234
1298
  Application: {
@@ -1250,7 +1314,12 @@ var schema_default = {
1250
1314
  },
1251
1315
  projectId: {
1252
1316
  type: "string",
1253
- description: "Vercel project ID"
1317
+ description: "Vercel project ID, only required if the application name / id is different to the Vercel project name.",
1318
+ deprecated: "Instead, the application id should match the Vercel project name."
1319
+ },
1320
+ packageName: {
1321
+ type: "string",
1322
+ 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`."
1254
1323
  },
1255
1324
  production: {
1256
1325
  $ref: "#/definitions/HostConfig",
@@ -1297,12 +1366,23 @@ var schema_default = {
1297
1366
  type: "object",
1298
1367
  properties: {
1299
1368
  local: {
1300
- $ref: "#/definitions/LocalHostConfig",
1301
- deprecated: "This is being replaced by the `localPort` field below."
1369
+ anyOf: [
1370
+ {
1371
+ type: "number"
1372
+ },
1373
+ {
1374
+ type: "string"
1375
+ },
1376
+ {
1377
+ $ref: "#/definitions/LocalHostConfig"
1378
+ }
1379
+ ],
1380
+ 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."
1302
1381
  },
1303
1382
  localPort: {
1304
1383
  type: "number",
1305
- 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."
1384
+ 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.",
1385
+ deprecated: "Please set the port with the 'local' field instead."
1306
1386
  },
1307
1387
  fallback: {
1308
1388
  anyOf: [
@@ -1313,7 +1393,7 @@ var schema_default = {
1313
1393
  type: "string"
1314
1394
  }
1315
1395
  ],
1316
- 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."
1396
+ 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."
1317
1397
  },
1318
1398
  task: {
1319
1399
  type: "string",
@@ -1350,7 +1430,12 @@ var schema_default = {
1350
1430
  },
1351
1431
  projectId: {
1352
1432
  type: "string",
1353
- description: "Vercel project ID"
1433
+ description: "Vercel project ID, only required if the application name / id is different to the Vercel project name.",
1434
+ deprecated: "Instead, the application id should match the Vercel project name."
1435
+ },
1436
+ packageName: {
1437
+ type: "string",
1438
+ 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`."
1354
1439
  },
1355
1440
  production: {
1356
1441
  $ref: "#/definitions/HostConfig",
@@ -1754,6 +1839,17 @@ function transform4(args) {
1754
1839
  } else {
1755
1840
  next.redirects = async () => proxyRedirects;
1756
1841
  }
1842
+ if (process.env.MFE_DEBUG) {
1843
+ const indent = " ".repeat(4);
1844
+ const header = "redirects";
1845
+ const separator = "\u23AF".repeat(header.length);
1846
+ console.log(
1847
+ `${indent}${header}
1848
+ ${indent}${separator}
1849
+ ${indent} - Automatically redirecting all requests to local microfrontends proxy
1850
+ `
1851
+ );
1852
+ }
1757
1853
  }
1758
1854
  return { next };
1759
1855
  }
@@ -1769,13 +1865,12 @@ function getDomainFromEnvironment({
1769
1865
  if (mfeProjects.length === 0) {
1770
1866
  throw new Error("Missing related microfrontends project information");
1771
1867
  }
1772
- if (!app.projectId) {
1773
- throw new Error(`Missing applications[${app.name}].vercel.projectId`);
1774
- }
1775
- const vercelProject = mfeProjects.find((p) => p.project.id === app.projectId);
1868
+ const vercelProject = mfeProjects.find(
1869
+ (p) => p.project.name === app.name || p.project.id === app.projectId
1870
+ );
1776
1871
  if (!vercelProject) {
1777
1872
  throw new Error(
1778
- `Missing related microfrontends project information for application "${app.name}"`
1873
+ `Could not find the Vercel project for application "${app.name}". If the name does not match the Vercel project name, set the \`projectId\` field in the application config.`
1779
1874
  );
1780
1875
  }
1781
1876
  const domain = target === "preview" && vercelProject.preview.branch ? vercelProject.preview.branch : vercelProject.production.alias ?? vercelProject.production.url;
@@ -1843,7 +1938,7 @@ function getDomainForCurrentEnvironment(config, appName, opts = {}) {
1843
1938
 
1844
1939
  // src/next/config/transforms/rewrites.ts
1845
1940
  function debugRewrites(rewrites) {
1846
- if (process.env.MFE_DEBUG === "true" || process.env.MFE_DEBUG === "1") {
1941
+ if (process.env.MFE_DEBUG) {
1847
1942
  const indent = " ".repeat(4);
1848
1943
  const header = "rewrites (source \u2192 destination)";
1849
1944
  const separator = "\u23AF".repeat(header.length);
@@ -2099,7 +2194,7 @@ var transforms = {
2099
2194
 
2100
2195
  // src/next/config/env.ts
2101
2196
  function debugEnv(env) {
2102
- if (process.env.MFE_DEBUG === "true") {
2197
+ if (process.env.MFE_DEBUG) {
2103
2198
  const indent = " ".repeat(4);
2104
2199
  const header = "env (key \u2192 val)";
2105
2200
  const separator = "\u23AF".repeat(header.length);