@vercel/microfrontends 0.17.4 → 0.19.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 (53) hide show
  1. package/README.md +7 -159
  2. package/dist/bin/cli.cjs +202 -139
  3. package/dist/config.cjs +103 -57
  4. package/dist/config.cjs.map +1 -1
  5. package/dist/config.d.ts +4 -4
  6. package/dist/config.js +103 -57
  7. package/dist/config.js.map +1 -1
  8. package/dist/{index-f094deb1.d.ts → index-09b1ddf9.d.ts} +16 -19
  9. package/dist/{index-5fcf0863.d.ts → index-2f78c0ca.d.ts} +44 -17
  10. package/dist/microfrontends/server.cjs +180 -133
  11. package/dist/microfrontends/server.cjs.map +1 -1
  12. package/dist/microfrontends/server.d.ts +4 -4
  13. package/dist/microfrontends/server.js +180 -133
  14. package/dist/microfrontends/server.js.map +1 -1
  15. package/dist/microfrontends.cjs +104 -58
  16. package/dist/microfrontends.cjs.map +1 -1
  17. package/dist/microfrontends.d.ts +4 -4
  18. package/dist/microfrontends.js +104 -58
  19. package/dist/microfrontends.js.map +1 -1
  20. package/dist/next/client.cjs +1 -1
  21. package/dist/next/client.cjs.map +1 -1
  22. package/dist/next/client.d.ts +1 -1
  23. package/dist/next/client.js +1 -1
  24. package/dist/next/client.js.map +1 -1
  25. package/dist/next/config.cjs +197 -145
  26. package/dist/next/config.cjs.map +1 -1
  27. package/dist/next/config.js +197 -145
  28. package/dist/next/config.js.map +1 -1
  29. package/dist/next/endpoints.d.ts +2 -2
  30. package/dist/next/middleware.cjs +121 -80
  31. package/dist/next/middleware.cjs.map +1 -1
  32. package/dist/next/middleware.js +121 -80
  33. package/dist/next/middleware.js.map +1 -1
  34. package/dist/next/testing.cjs +110 -63
  35. package/dist/next/testing.cjs.map +1 -1
  36. package/dist/next/testing.d.ts +4 -4
  37. package/dist/next/testing.js +110 -63
  38. package/dist/next/testing.js.map +1 -1
  39. package/dist/overrides.d.ts +3 -3
  40. package/dist/schema.d.ts +1 -1
  41. package/dist/{types-5900be7c.d.ts → types-4ef2bddb.d.ts} +1 -1
  42. package/dist/{types-ecd7b91b.d.ts → types-b6d38aea.d.ts} +1 -1
  43. package/dist/utils/mfe-port.cjs +181 -134
  44. package/dist/utils/mfe-port.cjs.map +1 -1
  45. package/dist/utils/mfe-port.js +181 -134
  46. package/dist/utils/mfe-port.js.map +1 -1
  47. package/dist/validation.cjs +74 -73
  48. package/dist/validation.cjs.map +1 -1
  49. package/dist/validation.d.ts +1 -1
  50. package/dist/validation.js +74 -73
  51. package/dist/validation.js.map +1 -1
  52. package/package.json +19 -3
  53. package/schema/schema.json +80 -73
@@ -76,7 +76,7 @@ function parseOverrides(cookies) {
76
76
  // src/config/errors.ts
77
77
  var MicrofrontendError = class extends Error {
78
78
  constructor(message, opts) {
79
- super(message);
79
+ super(message, { cause: opts?.cause });
80
80
  this.name = "MicrofrontendsError";
81
81
  this.source = opts?.source ?? "@vercel/microfrontends";
82
82
  this.type = opts?.type ?? "unknown";
@@ -268,7 +268,8 @@ var validateConfigPaths = (applicationConfigsById) => {
268
268
  if (isDefaultApp(app)) {
269
269
  continue;
270
270
  }
271
- for (const pathMatch of app.routing) {
271
+ const childApp = app;
272
+ for (const pathMatch of childApp.routing) {
272
273
  for (const path6 of pathMatch.paths) {
273
274
  const maybeError = validatePathExpression(path6);
274
275
  if (maybeError) {
@@ -288,33 +289,31 @@ var validateConfigPaths = (applicationConfigsById) => {
288
289
  }
289
290
  }
290
291
  const entries = Array.from(pathsByApplicationId.entries());
291
- entries.forEach(([path6, { applications: ids, matcher, applicationId }]) => {
292
+ for (const [path6, { applications: ids, matcher, applicationId }] of entries) {
292
293
  if (ids.length > 1) {
293
294
  errors.push(
294
295
  `Duplicate path "${path6}" for applications "${ids.join(", ")}"`
295
296
  );
296
297
  }
297
- entries.forEach(
298
- ([
299
- matchPath,
300
- { applications: matchIds, applicationId: matchApplicationId }
301
- ]) => {
302
- if (path6 === matchPath) {
303
- return;
304
- }
305
- if (applicationId === matchApplicationId) {
306
- return;
307
- }
308
- if (matcher.test(matchPath)) {
309
- const source = `"${path6}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
310
- const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
311
- errors.push(
312
- `Overlapping path detected between ${source} and ${destination}`
313
- );
314
- }
298
+ for (const [
299
+ matchPath,
300
+ { applications: matchIds, applicationId: matchApplicationId }
301
+ ] of entries) {
302
+ if (path6 === matchPath) {
303
+ continue;
315
304
  }
316
- );
317
- });
305
+ if (applicationId === matchApplicationId) {
306
+ continue;
307
+ }
308
+ if (matcher.test(matchPath)) {
309
+ const source = `"${path6}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
310
+ const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
311
+ errors.push(
312
+ `Overlapping path detected between ${source} and ${destination}`
313
+ );
314
+ }
315
+ }
316
+ }
318
317
  if (errors.length) {
319
318
  throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
320
319
  type: "config",
@@ -383,7 +382,7 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
383
382
  const numApplicationsWithoutRouting = numApplications - numApplicationsWithRouting;
384
383
  if (numApplicationsWithoutRouting === 0) {
385
384
  throw new MicrofrontendError(
386
- `No default application found. At least one application needs to be the default by omitting routing.`,
385
+ "No default application found. At least one application needs to be the default by omitting routing.",
387
386
  { type: "config", subtype: "no_default_application" }
388
387
  );
389
388
  }
@@ -429,47 +428,80 @@ function generatePortFromName({
429
428
  // src/config/microfrontends-config/isomorphic/host.ts
430
429
  var Host = class {
431
430
  constructor(hostConfig, options) {
432
- const { protocol = "https", host, port } = hostConfig;
433
- this.protocol = protocol;
434
- this.host = host;
435
- this.port = Host.getPort({ port, protocol: this.protocol });
431
+ if (typeof hostConfig === "string") {
432
+ ({
433
+ protocol: this.protocol,
434
+ host: this.host,
435
+ port: this.port
436
+ } = Host.parseUrl(hostConfig));
437
+ } else {
438
+ const { protocol = "https", host, port } = hostConfig;
439
+ this.protocol = protocol;
440
+ this.host = host;
441
+ this.port = port;
442
+ }
436
443
  this.local = options?.isLocal;
437
444
  }
438
- isLocal() {
439
- return this.local || this.host === "localhost" || this.host === "127.0.0.1";
440
- }
441
- static getPort({
442
- protocol,
443
- port
444
- }) {
445
- if (!port) {
446
- if (protocol === "http") {
447
- return 80;
448
- }
449
- return 443;
445
+ static parseUrl(url) {
446
+ let hostToParse = url;
447
+ if (!/^https?:\/\//.exec(hostToParse)) {
448
+ hostToParse = `https://${hostToParse}`;
449
+ }
450
+ const parsed = new URL(hostToParse);
451
+ if (!parsed.hostname) {
452
+ throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
453
+ }
454
+ if (parsed.hash) {
455
+ throw new Error(
456
+ Host.getMicrofrontendsError(url, "cannot have a fragment")
457
+ );
450
458
  }
451
- return port;
459
+ if (parsed.username || parsed.password) {
460
+ throw new Error(
461
+ Host.getMicrofrontendsError(
462
+ url,
463
+ "cannot have authentication credentials (username and/or password)"
464
+ )
465
+ );
466
+ }
467
+ if (parsed.pathname !== "/") {
468
+ throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
469
+ }
470
+ if (parsed.search) {
471
+ throw new Error(
472
+ Host.getMicrofrontendsError(url, "cannot have query parameters")
473
+ );
474
+ }
475
+ const protocol = parsed.protocol.slice(0, -1);
476
+ return {
477
+ protocol,
478
+ host: parsed.hostname,
479
+ port: parsed.port ? Number.parseInt(parsed.port) : void 0
480
+ };
452
481
  }
453
- isDefaultPort() {
454
- return this.port === Host.getPort({ protocol: this.protocol });
482
+ static getMicrofrontendsError(url, message) {
483
+ return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
484
+ }
485
+ isLocal() {
486
+ return this.local || this.host === "localhost" || this.host === "127.0.0.1";
455
487
  }
456
- toString(opts = {}) {
457
- const url = this.toUrl(opts);
488
+ toString() {
489
+ const url = this.toUrl();
458
490
  return url.toString().replace(/\/$/, "");
459
491
  }
460
- toUrl(opts = {}) {
461
- const { includeDefaultPort } = opts;
462
- const url = `${this.protocol}://${this.host}${this.isDefaultPort() && !includeDefaultPort ? "" : `:${this.port}`}`;
492
+ toUrl() {
493
+ const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
463
494
  return new URL(url);
464
495
  }
465
496
  };
466
497
  var LocalHost = class extends Host {
467
498
  constructor({
468
499
  appName,
500
+ localPort,
469
501
  ...hostConfig
470
502
  }) {
471
503
  const host = hostConfig.host ?? "localhost";
472
- const port = hostConfig.port ?? generatePortFromName({ name: appName });
504
+ const port = localPort ?? hostConfig.port ?? generatePortFromName({ name: appName });
473
505
  const protocol = hostConfig.protocol ?? "http";
474
506
  super({ protocol, host, port });
475
507
  }
@@ -486,12 +518,17 @@ var Application = class {
486
518
  this.development = {
487
519
  local: new LocalHost({
488
520
  appName: name,
521
+ localPort: app.development?.localPort,
489
522
  ...app.development?.local
490
523
  }),
491
524
  fallback: app.development?.fallback ? new Host(app.development.fallback) : void 0
492
525
  };
493
- this.production = app.production ? new Host(app.production) : void 0;
494
- this.vercel = app.vercel;
526
+ if (app.development?.fallback) {
527
+ this.fallback = new Host(app.development.fallback);
528
+ } else if (app.production) {
529
+ this.fallback = new Host(app.production);
530
+ }
531
+ this.projectId = app.projectId ?? app.vercel?.projectId;
495
532
  this.overrides = overrides?.environment ? {
496
533
  environment: new Host(overrides.environment)
497
534
  } : void 0;
@@ -519,7 +556,16 @@ var DefaultApplication = class extends Application {
519
556
  isDefault: true
520
557
  });
521
558
  this.default = true;
522
- this.production = new Host(app.production);
559
+ const fallbackHost = app.development?.fallback ?? app.production;
560
+ if (fallbackHost === void 0) {
561
+ throw new Error(
562
+ "`app.production` or `app.development.fallback` must be set in the default application in microfrontends.json."
563
+ );
564
+ }
565
+ this.fallback = new Host(fallbackHost);
566
+ if (app.production) {
567
+ this.production = new Host(app.production);
568
+ }
523
569
  }
524
570
  getAssetPrefix() {
525
571
  return "";
@@ -589,7 +635,7 @@ var MicrofrontendConfigIsomorphic = class {
589
635
  }
590
636
  if (isMainConfig(config) && !this.defaultApplication) {
591
637
  throw new MicrofrontendError(
592
- `Could not find default application in microfrontends configuration`,
638
+ "Could not find default application in microfrontends configuration",
593
639
  {
594
640
  type: "application",
595
641
  subtype: "not_found"
@@ -665,11 +711,11 @@ var MicrofrontendConfigIsomorphic = class {
665
711
  return app;
666
712
  }
667
713
  getApplicationByProjectId(projectId) {
668
- if (this.defaultApplication?.vercel?.projectId === projectId) {
714
+ if (this.defaultApplication?.projectId === projectId) {
669
715
  return this.defaultApplication;
670
716
  }
671
717
  return Object.values(this.childApplications).find(
672
- (app) => app.vercel?.projectId === projectId
718
+ (app) => app.projectId === projectId
673
719
  );
674
720
  }
675
721
  /**
@@ -679,7 +725,7 @@ var MicrofrontendConfigIsomorphic = class {
679
725
  getDefaultApplication() {
680
726
  if (!this.defaultApplication) {
681
727
  throw new MicrofrontendError(
682
- `Could not find default application in microfrontends configuration`,
728
+ "Could not find default application in microfrontends configuration",
683
729
  {
684
730
  type: "application",
685
731
  subtype: "not_found"
@@ -692,7 +738,7 @@ var MicrofrontendConfigIsomorphic = class {
692
738
  * Returns the configured port for the local proxy
693
739
  */
694
740
  getLocalProxyPort() {
695
- return this.config.options?.localProxy?.port ?? DEFAULT_LOCAL_PROXY_PORT;
741
+ return this.config.options?.localProxyPort ?? this.config.options?.localProxy?.port ?? DEFAULT_LOCAL_PROXY_PORT;
696
742
  }
697
743
  /**
698
744
  * Serializes the class back to the Schema type.
@@ -766,7 +812,7 @@ var MicrofrontendMainConfig = class extends MicrofrontendConfigIsomorphic {
766
812
  }
767
813
  if (!defaultApplication) {
768
814
  throw new MicrofrontendError(
769
- `Could not find default application in microfrontends configuration`,
815
+ "Could not find default application in microfrontends configuration",
770
816
  {
771
817
  type: "application",
772
818
  subtype: "not_found"
@@ -1053,24 +1099,12 @@ var schema_default = {
1053
1099
  options: {
1054
1100
  $ref: "#/definitions/Options"
1055
1101
  },
1056
- remotes: {
1057
- type: "object",
1058
- additionalProperties: {
1059
- $ref: "#/definitions/Application"
1060
- },
1061
- propertyNames: {
1062
- description: "The unique identifier for a Microfrontend Application. Must match the `name` field of the application's `package.json`."
1063
- },
1064
- description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
1065
- },
1066
1102
  applications: {
1067
1103
  $ref: "#/definitions/ApplicationRouting",
1068
1104
  description: "Mapping of application names to the routes that they host. Only needs to be defined in the application that owns the primary microfrontend domain"
1069
1105
  }
1070
1106
  },
1071
- required: [
1072
- "applications"
1073
- ],
1107
+ required: ["applications"],
1074
1108
  additionalProperties: false
1075
1109
  },
1076
1110
  Options: {
@@ -1078,11 +1112,21 @@ var schema_default = {
1078
1112
  properties: {
1079
1113
  vercel: {
1080
1114
  $ref: "#/definitions/VercelOptions",
1081
- description: "Micro-Frontends wide options for Vercel."
1115
+ description: "Microfrontends wide options for Vercel.",
1116
+ deprecated: "This is being replaced by the `disableOverrides` field below."
1117
+ },
1118
+ disableOverrides: {
1119
+ type: "boolean",
1120
+ description: "If you want to disable the overrides for the site. For example, if you are managing rewrites between applications externally, you may wish to disable the overrides on the toolbar as they will have no effect."
1082
1121
  },
1083
1122
  localProxy: {
1084
1123
  $ref: "#/definitions/LocalProxyOptions",
1085
- description: "Options for local proxy."
1124
+ description: "Options for local proxy.",
1125
+ deprecated: "This is being replaced by the `localProxyPort` field below."
1126
+ },
1127
+ localProxyPort: {
1128
+ type: "number",
1129
+ description: "The port number used by the local proxy server.\n\nThe default is `3024`."
1086
1130
  }
1087
1131
  },
1088
1132
  additionalProperties: false
@@ -1090,10 +1134,6 @@ var schema_default = {
1090
1134
  VercelOptions: {
1091
1135
  type: "object",
1092
1136
  properties: {
1093
- teamSlug: {
1094
- type: "string",
1095
- description: "Team slug for the Vercel team"
1096
- },
1097
1137
  disableOverrides: {
1098
1138
  type: "boolean",
1099
1139
  description: "If you want to disable the overrides for the site. For example, if you are managing rewrites between applications externally, you may wish to disable the overrides on the toolbar as they will have no effect."
@@ -1111,6 +1151,15 @@ var schema_default = {
1111
1151
  },
1112
1152
  additionalProperties: false
1113
1153
  },
1154
+ ApplicationRouting: {
1155
+ type: "object",
1156
+ additionalProperties: {
1157
+ $ref: "#/definitions/Application"
1158
+ },
1159
+ propertyNames: {
1160
+ description: "The unique identifier for a Microfrontend Application. Must match the `name` field of the application's `package.json`."
1161
+ }
1162
+ },
1114
1163
  Application: {
1115
1164
  anyOf: [
1116
1165
  {
@@ -1125,18 +1174,22 @@ var schema_default = {
1125
1174
  type: "object",
1126
1175
  properties: {
1127
1176
  vercel: {
1128
- $ref: "#/definitions/Vercel"
1177
+ $ref: "#/definitions/Vercel",
1178
+ deprecated: "This is being replaced by the `projectId` field below."
1179
+ },
1180
+ projectId: {
1181
+ type: "string",
1182
+ description: "Vercel project ID"
1129
1183
  },
1130
1184
  development: {
1131
1185
  $ref: "#/definitions/Development"
1132
1186
  },
1133
1187
  production: {
1134
- $ref: "#/definitions/HostConfig"
1188
+ $ref: "#/definitions/HostConfig",
1189
+ deprecated: "This is a duplicate of the `development.fallback` field and this will be removed soon."
1135
1190
  }
1136
1191
  },
1137
- required: [
1138
- "production"
1139
- ],
1192
+ required: ["production"],
1140
1193
  additionalProperties: false
1141
1194
  },
1142
1195
  Vercel: {
@@ -1147,20 +1200,30 @@ var schema_default = {
1147
1200
  description: "Vercel project ID"
1148
1201
  }
1149
1202
  },
1150
- required: [
1151
- "projectId"
1152
- ],
1203
+ required: ["projectId"],
1153
1204
  additionalProperties: false
1154
1205
  },
1155
1206
  Development: {
1156
1207
  type: "object",
1157
1208
  properties: {
1158
1209
  local: {
1159
- $ref: "#/definitions/LocalHostConfig"
1210
+ $ref: "#/definitions/LocalHostConfig",
1211
+ deprecated: "This is being replaced by the `localPort` field below."
1212
+ },
1213
+ localPort: {
1214
+ type: "number",
1215
+ 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."
1160
1216
  },
1161
1217
  fallback: {
1162
- $ref: "#/definitions/HostConfig",
1163
- 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."
1218
+ anyOf: [
1219
+ {
1220
+ $ref: "#/definitions/HostConfig"
1221
+ },
1222
+ {
1223
+ type: "string"
1224
+ }
1225
+ ],
1226
+ 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."
1164
1227
  },
1165
1228
  task: {
1166
1229
  type: "string",
@@ -1179,10 +1242,7 @@ var schema_default = {
1179
1242
  },
1180
1243
  protocol: {
1181
1244
  type: "string",
1182
- enum: [
1183
- "http",
1184
- "https"
1185
- ],
1245
+ enum: ["http", "https"],
1186
1246
  description: "The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n*"
1187
1247
  },
1188
1248
  port: {
@@ -1196,10 +1256,7 @@ var schema_default = {
1196
1256
  properties: {
1197
1257
  protocol: {
1198
1258
  type: "string",
1199
- enum: [
1200
- "http",
1201
- "https"
1202
- ],
1259
+ enum: ["http", "https"],
1203
1260
  description: "The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n*"
1204
1261
  },
1205
1262
  host: {
@@ -1211,16 +1268,19 @@ var schema_default = {
1211
1268
  description: "The port number to be used for the connection. Common values include `80` for HTTP and `443` for HTTPS."
1212
1269
  }
1213
1270
  },
1214
- required: [
1215
- "host"
1216
- ],
1271
+ required: ["host"],
1217
1272
  additionalProperties: false
1218
1273
  },
1219
1274
  ChildApplication: {
1220
1275
  type: "object",
1221
1276
  properties: {
1222
1277
  vercel: {
1223
- $ref: "#/definitions/Vercel"
1278
+ $ref: "#/definitions/Vercel",
1279
+ deprecated: "This is being replaced by the `projectId` field below."
1280
+ },
1281
+ projectId: {
1282
+ type: "string",
1283
+ description: "Vercel project ID"
1224
1284
  },
1225
1285
  development: {
1226
1286
  $ref: "#/definitions/Development"
@@ -1230,12 +1290,11 @@ var schema_default = {
1230
1290
  description: "Groups of path expressions that are routed to this application."
1231
1291
  },
1232
1292
  production: {
1233
- $ref: "#/definitions/HostConfig"
1293
+ $ref: "#/definitions/HostConfig",
1294
+ deprecated: "This is a duplicate of the `development.fallback` field and this will be removed soon."
1234
1295
  }
1235
1296
  },
1236
- required: [
1237
- "routing"
1238
- ],
1297
+ required: ["routing"],
1239
1298
  additionalProperties: false
1240
1299
  },
1241
1300
  Routing: {
@@ -1262,20 +1321,9 @@ var schema_default = {
1262
1321
  }
1263
1322
  }
1264
1323
  },
1265
- required: [
1266
- "paths"
1267
- ],
1324
+ required: ["paths"],
1268
1325
  additionalProperties: false
1269
1326
  },
1270
- ApplicationRouting: {
1271
- type: "object",
1272
- additionalProperties: {
1273
- $ref: "#/definitions/Application"
1274
- },
1275
- propertyNames: {
1276
- description: "The unique identifier for a Microfrontend Application. Must match the `name` field of the application's `package.json`."
1277
- }
1278
- },
1279
1327
  ChildConfig: {
1280
1328
  type: "object",
1281
1329
  properties: {
@@ -1289,24 +1337,12 @@ var schema_default = {
1289
1337
  options: {
1290
1338
  $ref: "#/definitions/Options"
1291
1339
  },
1292
- remotes: {
1293
- type: "object",
1294
- additionalProperties: {
1295
- $ref: "#/definitions/Application"
1296
- },
1297
- propertyNames: {
1298
- description: "The unique identifier for a Microfrontend Application. Must match the `name` field of the application's `package.json`."
1299
- },
1300
- description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
1301
- },
1302
1340
  partOf: {
1303
1341
  type: "string",
1304
1342
  description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
1305
1343
  }
1306
1344
  },
1307
- required: [
1308
- "partOf"
1309
- ],
1345
+ required: ["partOf"],
1310
1346
  additionalProperties: false
1311
1347
  }
1312
1348
  }
@@ -1316,6 +1352,14 @@ var schema_default = {
1316
1352
  var SCHEMA = schema_default;
1317
1353
 
1318
1354
  // src/config/microfrontends/server/validation.ts
1355
+ function filterAjvErrors(errors) {
1356
+ if (!errors) {
1357
+ return [];
1358
+ }
1359
+ return errors.filter((error) => {
1360
+ return error.keyword === "additionalProperties" || error.keyword === "required";
1361
+ });
1362
+ }
1319
1363
  function validateSchema(configString) {
1320
1364
  const parsedConfig = (0, import_jsonc_parser3.parse)(configString);
1321
1365
  const ajv = new import_ajv.Ajv();
@@ -1323,7 +1367,10 @@ function validateSchema(configString) {
1323
1367
  const isValid = validate(parsedConfig);
1324
1368
  if (!isValid) {
1325
1369
  throw new MicrofrontendError(
1326
- `Invalid config: ${ajv.errorsText(validate.errors)}`,
1370
+ `Invalid microfrontends config:
1371
+ - ${ajv.errorsText(filterAjvErrors(validate.errors), { separator: "\n - " })}
1372
+
1373
+ See https://openapi.vercel.sh/microfrontends.json for the schema.`,
1327
1374
  { type: "config", subtype: "does_not_match_schema" }
1328
1375
  );
1329
1376
  }
@@ -1463,8 +1510,8 @@ var MicrofrontendsServer = class extends Microfrontends {
1463
1510
  throw new Error("Unable to infer");
1464
1511
  } catch (e) {
1465
1512
  throw new MicrofrontendError(
1466
- "Unable to infer microfrontends configuration",
1467
- { type: "config", subtype: "inference_failed" }
1513
+ "Unable to locate and parse microfrontends configuration",
1514
+ { cause: e, type: "config", subtype: "inference_failed" }
1468
1515
  );
1469
1516
  }
1470
1517
  }
@@ -1540,7 +1587,7 @@ var MicrofrontendsServer = class extends Microfrontends {
1540
1587
  const [defaultApplication] = Object.entries(validatedConfig.applications).filter(([, app]) => isDefaultApp(app)).map(([name]) => name);
1541
1588
  if (!defaultApplication) {
1542
1589
  throw new MicrofrontendError(
1543
- `No default application found. At least one application needs to be the default by omitting routing.`,
1590
+ "No default application found. At least one application needs to be the default by omitting routing.",
1544
1591
  { type: "config", subtype: "no_default_application" }
1545
1592
  );
1546
1593
  }
@@ -1593,7 +1640,7 @@ function loadConfig({
1593
1640
  return void 0;
1594
1641
  }
1595
1642
  const app = config.config.getApplication(appName);
1596
- const port = app.development.local.port;
1643
+ const port = app.development.local.port ?? (app.development.local.protocol === "https" ? 443 : 80);
1597
1644
  return { port };
1598
1645
  }
1599
1646
  // Annotate the CommonJS export names for ESM import in node: