@vercel/microfrontends 0.18.0 → 0.19.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.
- package/dist/bin/cli.cjs +151 -71
- package/dist/config.cjs +102 -56
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.ts +4 -4
- package/dist/config.js +102 -56
- package/dist/config.js.map +1 -1
- package/dist/{index-24024799.d.ts → index-09b1ddf9.d.ts} +16 -19
- package/dist/{index-ef8657e6.d.ts → index-2f78c0ca.d.ts} +44 -7
- package/dist/microfrontends/server.cjs +147 -67
- package/dist/microfrontends/server.cjs.map +1 -1
- package/dist/microfrontends/server.d.ts +4 -4
- package/dist/microfrontends/server.js +147 -67
- package/dist/microfrontends/server.js.map +1 -1
- package/dist/microfrontends.cjs +103 -57
- package/dist/microfrontends.cjs.map +1 -1
- package/dist/microfrontends.d.ts +4 -4
- package/dist/microfrontends.js +103 -57
- package/dist/microfrontends.js.map +1 -1
- package/dist/next/config.cjs +166 -79
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.js +166 -79
- package/dist/next/config.js.map +1 -1
- package/dist/next/endpoints.d.ts +2 -2
- package/dist/next/middleware.cjs +120 -75
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.js +120 -75
- package/dist/next/middleware.js.map +1 -1
- package/dist/next/testing.cjs +109 -62
- package/dist/next/testing.cjs.map +1 -1
- package/dist/next/testing.d.ts +4 -4
- package/dist/next/testing.js +109 -62
- package/dist/next/testing.js.map +1 -1
- package/dist/overrides.d.ts +3 -3
- package/dist/schema.d.ts +1 -1
- package/dist/{types-089498fd.d.ts → types-4ef2bddb.d.ts} +1 -1
- package/dist/{types-9f161cec.d.ts → types-b6d38aea.d.ts} +1 -1
- package/dist/utils/mfe-port.cjs +148 -68
- package/dist/utils/mfe-port.cjs.map +1 -1
- package/dist/utils/mfe-port.js +148 -68
- package/dist/utils/mfe-port.js.map +1 -1
- package/dist/validation.cjs +43 -9
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.d.ts +1 -1
- package/dist/validation.js +43 -9
- package/dist/validation.js.map +1 -1
- package/package.json +1 -1
- package/schema/schema.json +71 -40
|
@@ -230,7 +230,8 @@ var validateConfigPaths = (applicationConfigsById) => {
|
|
|
230
230
|
if (isDefaultApp(app)) {
|
|
231
231
|
continue;
|
|
232
232
|
}
|
|
233
|
-
|
|
233
|
+
const childApp = app;
|
|
234
|
+
for (const pathMatch of childApp.routing) {
|
|
234
235
|
for (const path5 of pathMatch.paths) {
|
|
235
236
|
const maybeError = validatePathExpression(path5);
|
|
236
237
|
if (maybeError) {
|
|
@@ -250,33 +251,31 @@ var validateConfigPaths = (applicationConfigsById) => {
|
|
|
250
251
|
}
|
|
251
252
|
}
|
|
252
253
|
const entries = Array.from(pathsByApplicationId.entries());
|
|
253
|
-
|
|
254
|
+
for (const [path5, { applications: ids, matcher, applicationId }] of entries) {
|
|
254
255
|
if (ids.length > 1) {
|
|
255
256
|
errors.push(
|
|
256
257
|
`Duplicate path "${path5}" for applications "${ids.join(", ")}"`
|
|
257
258
|
);
|
|
258
259
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
if (applicationId === matchApplicationId) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
if (matcher.test(matchPath)) {
|
|
271
|
-
const source = `"${path5}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
272
|
-
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
273
|
-
errors.push(
|
|
274
|
-
`Overlapping path detected between ${source} and ${destination}`
|
|
275
|
-
);
|
|
276
|
-
}
|
|
260
|
+
for (const [
|
|
261
|
+
matchPath,
|
|
262
|
+
{ applications: matchIds, applicationId: matchApplicationId }
|
|
263
|
+
] of entries) {
|
|
264
|
+
if (path5 === matchPath) {
|
|
265
|
+
continue;
|
|
277
266
|
}
|
|
278
|
-
|
|
279
|
-
|
|
267
|
+
if (applicationId === matchApplicationId) {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (matcher.test(matchPath)) {
|
|
271
|
+
const source = `"${path5}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
272
|
+
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
273
|
+
errors.push(
|
|
274
|
+
`Overlapping path detected between ${source} and ${destination}`
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
280
279
|
if (errors.length) {
|
|
281
280
|
throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
|
|
282
281
|
type: "config",
|
|
@@ -345,7 +344,7 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
|
|
|
345
344
|
const numApplicationsWithoutRouting = numApplications - numApplicationsWithRouting;
|
|
346
345
|
if (numApplicationsWithoutRouting === 0) {
|
|
347
346
|
throw new MicrofrontendError(
|
|
348
|
-
|
|
347
|
+
"No default application found. At least one application needs to be the default by omitting routing.",
|
|
349
348
|
{ type: "config", subtype: "no_default_application" }
|
|
350
349
|
);
|
|
351
350
|
}
|
|
@@ -391,47 +390,80 @@ function generatePortFromName({
|
|
|
391
390
|
// src/config/microfrontends-config/isomorphic/host.ts
|
|
392
391
|
var Host = class {
|
|
393
392
|
constructor(hostConfig, options) {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
393
|
+
if (typeof hostConfig === "string") {
|
|
394
|
+
({
|
|
395
|
+
protocol: this.protocol,
|
|
396
|
+
host: this.host,
|
|
397
|
+
port: this.port
|
|
398
|
+
} = Host.parseUrl(hostConfig));
|
|
399
|
+
} else {
|
|
400
|
+
const { protocol = "https", host, port } = hostConfig;
|
|
401
|
+
this.protocol = protocol;
|
|
402
|
+
this.host = host;
|
|
403
|
+
this.port = port;
|
|
404
|
+
}
|
|
398
405
|
this.local = options?.isLocal;
|
|
399
406
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
if (protocol === "http") {
|
|
409
|
-
return 80;
|
|
410
|
-
}
|
|
411
|
-
return 443;
|
|
407
|
+
static parseUrl(url) {
|
|
408
|
+
let hostToParse = url;
|
|
409
|
+
if (!/^https?:\/\//.exec(hostToParse)) {
|
|
410
|
+
hostToParse = `https://${hostToParse}`;
|
|
411
|
+
}
|
|
412
|
+
const parsed = new URL(hostToParse);
|
|
413
|
+
if (!parsed.hostname) {
|
|
414
|
+
throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
|
|
412
415
|
}
|
|
413
|
-
|
|
416
|
+
if (parsed.hash) {
|
|
417
|
+
throw new Error(
|
|
418
|
+
Host.getMicrofrontendsError(url, "cannot have a fragment")
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
if (parsed.username || parsed.password) {
|
|
422
|
+
throw new Error(
|
|
423
|
+
Host.getMicrofrontendsError(
|
|
424
|
+
url,
|
|
425
|
+
"cannot have authentication credentials (username and/or password)"
|
|
426
|
+
)
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
if (parsed.pathname !== "/") {
|
|
430
|
+
throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
|
|
431
|
+
}
|
|
432
|
+
if (parsed.search) {
|
|
433
|
+
throw new Error(
|
|
434
|
+
Host.getMicrofrontendsError(url, "cannot have query parameters")
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
const protocol = parsed.protocol.slice(0, -1);
|
|
438
|
+
return {
|
|
439
|
+
protocol,
|
|
440
|
+
host: parsed.hostname,
|
|
441
|
+
port: parsed.port ? Number.parseInt(parsed.port) : void 0
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
static getMicrofrontendsError(url, message) {
|
|
445
|
+
return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
|
|
414
446
|
}
|
|
415
|
-
|
|
416
|
-
return this.
|
|
447
|
+
isLocal() {
|
|
448
|
+
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
417
449
|
}
|
|
418
|
-
toString(
|
|
419
|
-
const url = this.toUrl(
|
|
450
|
+
toString() {
|
|
451
|
+
const url = this.toUrl();
|
|
420
452
|
return url.toString().replace(/\/$/, "");
|
|
421
453
|
}
|
|
422
|
-
toUrl(
|
|
423
|
-
const {
|
|
424
|
-
const url = `${this.protocol}://${this.host}${this.isDefaultPort() && !includeDefaultPort ? "" : `:${this.port}`}`;
|
|
454
|
+
toUrl() {
|
|
455
|
+
const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
|
|
425
456
|
return new URL(url);
|
|
426
457
|
}
|
|
427
458
|
};
|
|
428
459
|
var LocalHost = class extends Host {
|
|
429
460
|
constructor({
|
|
430
461
|
appName,
|
|
462
|
+
localPort,
|
|
431
463
|
...hostConfig
|
|
432
464
|
}) {
|
|
433
465
|
const host = hostConfig.host ?? "localhost";
|
|
434
|
-
const port = hostConfig.port ?? generatePortFromName({ name: appName });
|
|
466
|
+
const port = localPort ?? hostConfig.port ?? generatePortFromName({ name: appName });
|
|
435
467
|
const protocol = hostConfig.protocol ?? "http";
|
|
436
468
|
super({ protocol, host, port });
|
|
437
469
|
}
|
|
@@ -448,12 +480,17 @@ var Application = class {
|
|
|
448
480
|
this.development = {
|
|
449
481
|
local: new LocalHost({
|
|
450
482
|
appName: name,
|
|
483
|
+
localPort: app.development?.localPort,
|
|
451
484
|
...app.development?.local
|
|
452
485
|
}),
|
|
453
486
|
fallback: app.development?.fallback ? new Host(app.development.fallback) : void 0
|
|
454
487
|
};
|
|
455
|
-
|
|
456
|
-
|
|
488
|
+
if (app.development?.fallback) {
|
|
489
|
+
this.fallback = new Host(app.development.fallback);
|
|
490
|
+
} else if (app.production) {
|
|
491
|
+
this.fallback = new Host(app.production);
|
|
492
|
+
}
|
|
493
|
+
this.projectId = app.projectId ?? app.vercel?.projectId;
|
|
457
494
|
this.overrides = overrides?.environment ? {
|
|
458
495
|
environment: new Host(overrides.environment)
|
|
459
496
|
} : void 0;
|
|
@@ -481,7 +518,16 @@ var DefaultApplication = class extends Application {
|
|
|
481
518
|
isDefault: true
|
|
482
519
|
});
|
|
483
520
|
this.default = true;
|
|
484
|
-
|
|
521
|
+
const fallbackHost = app.development?.fallback ?? app.production;
|
|
522
|
+
if (fallbackHost === void 0) {
|
|
523
|
+
throw new Error(
|
|
524
|
+
"`app.production` or `app.development.fallback` must be set in the default application in microfrontends.json."
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
this.fallback = new Host(fallbackHost);
|
|
528
|
+
if (app.production) {
|
|
529
|
+
this.production = new Host(app.production);
|
|
530
|
+
}
|
|
485
531
|
}
|
|
486
532
|
getAssetPrefix() {
|
|
487
533
|
return "";
|
|
@@ -551,7 +597,7 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
551
597
|
}
|
|
552
598
|
if (isMainConfig(config) && !this.defaultApplication) {
|
|
553
599
|
throw new MicrofrontendError(
|
|
554
|
-
|
|
600
|
+
"Could not find default application in microfrontends configuration",
|
|
555
601
|
{
|
|
556
602
|
type: "application",
|
|
557
603
|
subtype: "not_found"
|
|
@@ -627,11 +673,11 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
627
673
|
return app;
|
|
628
674
|
}
|
|
629
675
|
getApplicationByProjectId(projectId) {
|
|
630
|
-
if (this.defaultApplication?.
|
|
676
|
+
if (this.defaultApplication?.projectId === projectId) {
|
|
631
677
|
return this.defaultApplication;
|
|
632
678
|
}
|
|
633
679
|
return Object.values(this.childApplications).find(
|
|
634
|
-
(app) => app.
|
|
680
|
+
(app) => app.projectId === projectId
|
|
635
681
|
);
|
|
636
682
|
}
|
|
637
683
|
/**
|
|
@@ -641,7 +687,7 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
641
687
|
getDefaultApplication() {
|
|
642
688
|
if (!this.defaultApplication) {
|
|
643
689
|
throw new MicrofrontendError(
|
|
644
|
-
|
|
690
|
+
"Could not find default application in microfrontends configuration",
|
|
645
691
|
{
|
|
646
692
|
type: "application",
|
|
647
693
|
subtype: "not_found"
|
|
@@ -654,7 +700,7 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
654
700
|
* Returns the configured port for the local proxy
|
|
655
701
|
*/
|
|
656
702
|
getLocalProxyPort() {
|
|
657
|
-
return this.config.options?.localProxy?.port ?? DEFAULT_LOCAL_PROXY_PORT;
|
|
703
|
+
return this.config.options?.localProxyPort ?? this.config.options?.localProxy?.port ?? DEFAULT_LOCAL_PROXY_PORT;
|
|
658
704
|
}
|
|
659
705
|
/**
|
|
660
706
|
* Serializes the class back to the Schema type.
|
|
@@ -728,7 +774,7 @@ var MicrofrontendMainConfig = class extends MicrofrontendConfigIsomorphic {
|
|
|
728
774
|
}
|
|
729
775
|
if (!defaultApplication) {
|
|
730
776
|
throw new MicrofrontendError(
|
|
731
|
-
|
|
777
|
+
"Could not find default application in microfrontends configuration",
|
|
732
778
|
{
|
|
733
779
|
type: "application",
|
|
734
780
|
subtype: "not_found"
|
|
@@ -1028,11 +1074,21 @@ var schema_default = {
|
|
|
1028
1074
|
properties: {
|
|
1029
1075
|
vercel: {
|
|
1030
1076
|
$ref: "#/definitions/VercelOptions",
|
|
1031
|
-
description: "
|
|
1077
|
+
description: "Microfrontends wide options for Vercel.",
|
|
1078
|
+
deprecated: "This is being replaced by the `disableOverrides` field below."
|
|
1079
|
+
},
|
|
1080
|
+
disableOverrides: {
|
|
1081
|
+
type: "boolean",
|
|
1082
|
+
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."
|
|
1032
1083
|
},
|
|
1033
1084
|
localProxy: {
|
|
1034
1085
|
$ref: "#/definitions/LocalProxyOptions",
|
|
1035
|
-
description: "Options for local proxy."
|
|
1086
|
+
description: "Options for local proxy.",
|
|
1087
|
+
deprecated: "This is being replaced by the `localProxyPort` field below."
|
|
1088
|
+
},
|
|
1089
|
+
localProxyPort: {
|
|
1090
|
+
type: "number",
|
|
1091
|
+
description: "The port number used by the local proxy server.\n\nThe default is `3024`."
|
|
1036
1092
|
}
|
|
1037
1093
|
},
|
|
1038
1094
|
additionalProperties: false
|
|
@@ -1080,13 +1136,19 @@ var schema_default = {
|
|
|
1080
1136
|
type: "object",
|
|
1081
1137
|
properties: {
|
|
1082
1138
|
vercel: {
|
|
1083
|
-
$ref: "#/definitions/Vercel"
|
|
1139
|
+
$ref: "#/definitions/Vercel",
|
|
1140
|
+
deprecated: "This is being replaced by the `projectId` field below."
|
|
1141
|
+
},
|
|
1142
|
+
projectId: {
|
|
1143
|
+
type: "string",
|
|
1144
|
+
description: "Vercel project ID"
|
|
1084
1145
|
},
|
|
1085
1146
|
development: {
|
|
1086
1147
|
$ref: "#/definitions/Development"
|
|
1087
1148
|
},
|
|
1088
1149
|
production: {
|
|
1089
|
-
$ref: "#/definitions/HostConfig"
|
|
1150
|
+
$ref: "#/definitions/HostConfig",
|
|
1151
|
+
deprecated: "This is a duplicate of the `development.fallback` field and this will be removed soon."
|
|
1090
1152
|
}
|
|
1091
1153
|
},
|
|
1092
1154
|
required: ["production"],
|
|
@@ -1107,11 +1169,23 @@ var schema_default = {
|
|
|
1107
1169
|
type: "object",
|
|
1108
1170
|
properties: {
|
|
1109
1171
|
local: {
|
|
1110
|
-
$ref: "#/definitions/LocalHostConfig"
|
|
1172
|
+
$ref: "#/definitions/LocalHostConfig",
|
|
1173
|
+
deprecated: "This is being replaced by the `localPort` field below."
|
|
1174
|
+
},
|
|
1175
|
+
localPort: {
|
|
1176
|
+
type: "number",
|
|
1177
|
+
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."
|
|
1111
1178
|
},
|
|
1112
1179
|
fallback: {
|
|
1113
|
-
|
|
1114
|
-
|
|
1180
|
+
anyOf: [
|
|
1181
|
+
{
|
|
1182
|
+
$ref: "#/definitions/HostConfig"
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
type: "string"
|
|
1186
|
+
}
|
|
1187
|
+
],
|
|
1188
|
+
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."
|
|
1115
1189
|
},
|
|
1116
1190
|
task: {
|
|
1117
1191
|
type: "string",
|
|
@@ -1163,7 +1237,12 @@ var schema_default = {
|
|
|
1163
1237
|
type: "object",
|
|
1164
1238
|
properties: {
|
|
1165
1239
|
vercel: {
|
|
1166
|
-
$ref: "#/definitions/Vercel"
|
|
1240
|
+
$ref: "#/definitions/Vercel",
|
|
1241
|
+
deprecated: "This is being replaced by the `projectId` field below."
|
|
1242
|
+
},
|
|
1243
|
+
projectId: {
|
|
1244
|
+
type: "string",
|
|
1245
|
+
description: "Vercel project ID"
|
|
1167
1246
|
},
|
|
1168
1247
|
development: {
|
|
1169
1248
|
$ref: "#/definitions/Development"
|
|
@@ -1173,7 +1252,8 @@ var schema_default = {
|
|
|
1173
1252
|
description: "Groups of path expressions that are routed to this application."
|
|
1174
1253
|
},
|
|
1175
1254
|
production: {
|
|
1176
|
-
$ref: "#/definitions/HostConfig"
|
|
1255
|
+
$ref: "#/definitions/HostConfig",
|
|
1256
|
+
deprecated: "This is a duplicate of the `development.fallback` field and this will be removed soon."
|
|
1177
1257
|
}
|
|
1178
1258
|
},
|
|
1179
1259
|
required: ["routing"],
|
|
@@ -1469,7 +1549,7 @@ var MicrofrontendsServer = class extends Microfrontends {
|
|
|
1469
1549
|
const [defaultApplication] = Object.entries(validatedConfig.applications).filter(([, app]) => isDefaultApp(app)).map(([name]) => name);
|
|
1470
1550
|
if (!defaultApplication) {
|
|
1471
1551
|
throw new MicrofrontendError(
|
|
1472
|
-
|
|
1552
|
+
"No default application found. At least one application needs to be the default by omitting routing.",
|
|
1473
1553
|
{ type: "config", subtype: "no_default_application" }
|
|
1474
1554
|
);
|
|
1475
1555
|
}
|