@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
|
@@ -264,7 +264,8 @@ var validateConfigPaths = (applicationConfigsById) => {
|
|
|
264
264
|
if (isDefaultApp(app)) {
|
|
265
265
|
continue;
|
|
266
266
|
}
|
|
267
|
-
|
|
267
|
+
const childApp = app;
|
|
268
|
+
for (const pathMatch of childApp.routing) {
|
|
268
269
|
for (const path5 of pathMatch.paths) {
|
|
269
270
|
const maybeError = validatePathExpression(path5);
|
|
270
271
|
if (maybeError) {
|
|
@@ -284,33 +285,31 @@ var validateConfigPaths = (applicationConfigsById) => {
|
|
|
284
285
|
}
|
|
285
286
|
}
|
|
286
287
|
const entries = Array.from(pathsByApplicationId.entries());
|
|
287
|
-
|
|
288
|
+
for (const [path5, { applications: ids, matcher, applicationId }] of entries) {
|
|
288
289
|
if (ids.length > 1) {
|
|
289
290
|
errors.push(
|
|
290
291
|
`Duplicate path "${path5}" for applications "${ids.join(", ")}"`
|
|
291
292
|
);
|
|
292
293
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
if (applicationId === matchApplicationId) {
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
if (matcher.test(matchPath)) {
|
|
305
|
-
const source = `"${path5}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
306
|
-
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
307
|
-
errors.push(
|
|
308
|
-
`Overlapping path detected between ${source} and ${destination}`
|
|
309
|
-
);
|
|
310
|
-
}
|
|
294
|
+
for (const [
|
|
295
|
+
matchPath,
|
|
296
|
+
{ applications: matchIds, applicationId: matchApplicationId }
|
|
297
|
+
] of entries) {
|
|
298
|
+
if (path5 === matchPath) {
|
|
299
|
+
continue;
|
|
311
300
|
}
|
|
312
|
-
|
|
313
|
-
|
|
301
|
+
if (applicationId === matchApplicationId) {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
if (matcher.test(matchPath)) {
|
|
305
|
+
const source = `"${path5}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
306
|
+
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
307
|
+
errors.push(
|
|
308
|
+
`Overlapping path detected between ${source} and ${destination}`
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
314
313
|
if (errors.length) {
|
|
315
314
|
throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
|
|
316
315
|
type: "config",
|
|
@@ -379,7 +378,7 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
|
|
|
379
378
|
const numApplicationsWithoutRouting = numApplications - numApplicationsWithRouting;
|
|
380
379
|
if (numApplicationsWithoutRouting === 0) {
|
|
381
380
|
throw new MicrofrontendError(
|
|
382
|
-
|
|
381
|
+
"No default application found. At least one application needs to be the default by omitting routing.",
|
|
383
382
|
{ type: "config", subtype: "no_default_application" }
|
|
384
383
|
);
|
|
385
384
|
}
|
|
@@ -425,47 +424,80 @@ function generatePortFromName({
|
|
|
425
424
|
// src/config/microfrontends-config/isomorphic/host.ts
|
|
426
425
|
var Host = class {
|
|
427
426
|
constructor(hostConfig, options) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
427
|
+
if (typeof hostConfig === "string") {
|
|
428
|
+
({
|
|
429
|
+
protocol: this.protocol,
|
|
430
|
+
host: this.host,
|
|
431
|
+
port: this.port
|
|
432
|
+
} = Host.parseUrl(hostConfig));
|
|
433
|
+
} else {
|
|
434
|
+
const { protocol = "https", host, port } = hostConfig;
|
|
435
|
+
this.protocol = protocol;
|
|
436
|
+
this.host = host;
|
|
437
|
+
this.port = port;
|
|
438
|
+
}
|
|
432
439
|
this.local = options?.isLocal;
|
|
433
440
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
if (protocol === "http") {
|
|
443
|
-
return 80;
|
|
444
|
-
}
|
|
445
|
-
return 443;
|
|
441
|
+
static parseUrl(url) {
|
|
442
|
+
let hostToParse = url;
|
|
443
|
+
if (!/^https?:\/\//.exec(hostToParse)) {
|
|
444
|
+
hostToParse = `https://${hostToParse}`;
|
|
445
|
+
}
|
|
446
|
+
const parsed = new URL(hostToParse);
|
|
447
|
+
if (!parsed.hostname) {
|
|
448
|
+
throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
|
|
446
449
|
}
|
|
447
|
-
|
|
450
|
+
if (parsed.hash) {
|
|
451
|
+
throw new Error(
|
|
452
|
+
Host.getMicrofrontendsError(url, "cannot have a fragment")
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
if (parsed.username || parsed.password) {
|
|
456
|
+
throw new Error(
|
|
457
|
+
Host.getMicrofrontendsError(
|
|
458
|
+
url,
|
|
459
|
+
"cannot have authentication credentials (username and/or password)"
|
|
460
|
+
)
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
if (parsed.pathname !== "/") {
|
|
464
|
+
throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
|
|
465
|
+
}
|
|
466
|
+
if (parsed.search) {
|
|
467
|
+
throw new Error(
|
|
468
|
+
Host.getMicrofrontendsError(url, "cannot have query parameters")
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
const protocol = parsed.protocol.slice(0, -1);
|
|
472
|
+
return {
|
|
473
|
+
protocol,
|
|
474
|
+
host: parsed.hostname,
|
|
475
|
+
port: parsed.port ? Number.parseInt(parsed.port) : void 0
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
static getMicrofrontendsError(url, message) {
|
|
479
|
+
return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
|
|
448
480
|
}
|
|
449
|
-
|
|
450
|
-
return this.
|
|
481
|
+
isLocal() {
|
|
482
|
+
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
451
483
|
}
|
|
452
|
-
toString(
|
|
453
|
-
const url = this.toUrl(
|
|
484
|
+
toString() {
|
|
485
|
+
const url = this.toUrl();
|
|
454
486
|
return url.toString().replace(/\/$/, "");
|
|
455
487
|
}
|
|
456
|
-
toUrl(
|
|
457
|
-
const {
|
|
458
|
-
const url = `${this.protocol}://${this.host}${this.isDefaultPort() && !includeDefaultPort ? "" : `:${this.port}`}`;
|
|
488
|
+
toUrl() {
|
|
489
|
+
const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
|
|
459
490
|
return new URL(url);
|
|
460
491
|
}
|
|
461
492
|
};
|
|
462
493
|
var LocalHost = class extends Host {
|
|
463
494
|
constructor({
|
|
464
495
|
appName,
|
|
496
|
+
localPort,
|
|
465
497
|
...hostConfig
|
|
466
498
|
}) {
|
|
467
499
|
const host = hostConfig.host ?? "localhost";
|
|
468
|
-
const port = hostConfig.port ?? generatePortFromName({ name: appName });
|
|
500
|
+
const port = localPort ?? hostConfig.port ?? generatePortFromName({ name: appName });
|
|
469
501
|
const protocol = hostConfig.protocol ?? "http";
|
|
470
502
|
super({ protocol, host, port });
|
|
471
503
|
}
|
|
@@ -482,12 +514,17 @@ var Application = class {
|
|
|
482
514
|
this.development = {
|
|
483
515
|
local: new LocalHost({
|
|
484
516
|
appName: name,
|
|
517
|
+
localPort: app.development?.localPort,
|
|
485
518
|
...app.development?.local
|
|
486
519
|
}),
|
|
487
520
|
fallback: app.development?.fallback ? new Host(app.development.fallback) : void 0
|
|
488
521
|
};
|
|
489
|
-
|
|
490
|
-
|
|
522
|
+
if (app.development?.fallback) {
|
|
523
|
+
this.fallback = new Host(app.development.fallback);
|
|
524
|
+
} else if (app.production) {
|
|
525
|
+
this.fallback = new Host(app.production);
|
|
526
|
+
}
|
|
527
|
+
this.projectId = app.projectId ?? app.vercel?.projectId;
|
|
491
528
|
this.overrides = overrides?.environment ? {
|
|
492
529
|
environment: new Host(overrides.environment)
|
|
493
530
|
} : void 0;
|
|
@@ -515,7 +552,16 @@ var DefaultApplication = class extends Application {
|
|
|
515
552
|
isDefault: true
|
|
516
553
|
});
|
|
517
554
|
this.default = true;
|
|
518
|
-
|
|
555
|
+
const fallbackHost = app.development?.fallback ?? app.production;
|
|
556
|
+
if (fallbackHost === void 0) {
|
|
557
|
+
throw new Error(
|
|
558
|
+
"`app.production` or `app.development.fallback` must be set in the default application in microfrontends.json."
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
this.fallback = new Host(fallbackHost);
|
|
562
|
+
if (app.production) {
|
|
563
|
+
this.production = new Host(app.production);
|
|
564
|
+
}
|
|
519
565
|
}
|
|
520
566
|
getAssetPrefix() {
|
|
521
567
|
return "";
|
|
@@ -585,7 +631,7 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
585
631
|
}
|
|
586
632
|
if (isMainConfig(config) && !this.defaultApplication) {
|
|
587
633
|
throw new MicrofrontendError(
|
|
588
|
-
|
|
634
|
+
"Could not find default application in microfrontends configuration",
|
|
589
635
|
{
|
|
590
636
|
type: "application",
|
|
591
637
|
subtype: "not_found"
|
|
@@ -661,11 +707,11 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
661
707
|
return app;
|
|
662
708
|
}
|
|
663
709
|
getApplicationByProjectId(projectId) {
|
|
664
|
-
if (this.defaultApplication?.
|
|
710
|
+
if (this.defaultApplication?.projectId === projectId) {
|
|
665
711
|
return this.defaultApplication;
|
|
666
712
|
}
|
|
667
713
|
return Object.values(this.childApplications).find(
|
|
668
|
-
(app) => app.
|
|
714
|
+
(app) => app.projectId === projectId
|
|
669
715
|
);
|
|
670
716
|
}
|
|
671
717
|
/**
|
|
@@ -675,7 +721,7 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
675
721
|
getDefaultApplication() {
|
|
676
722
|
if (!this.defaultApplication) {
|
|
677
723
|
throw new MicrofrontendError(
|
|
678
|
-
|
|
724
|
+
"Could not find default application in microfrontends configuration",
|
|
679
725
|
{
|
|
680
726
|
type: "application",
|
|
681
727
|
subtype: "not_found"
|
|
@@ -688,7 +734,7 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
688
734
|
* Returns the configured port for the local proxy
|
|
689
735
|
*/
|
|
690
736
|
getLocalProxyPort() {
|
|
691
|
-
return this.config.options?.localProxy?.port ?? DEFAULT_LOCAL_PROXY_PORT;
|
|
737
|
+
return this.config.options?.localProxyPort ?? this.config.options?.localProxy?.port ?? DEFAULT_LOCAL_PROXY_PORT;
|
|
692
738
|
}
|
|
693
739
|
/**
|
|
694
740
|
* Serializes the class back to the Schema type.
|
|
@@ -762,7 +808,7 @@ var MicrofrontendMainConfig = class extends MicrofrontendConfigIsomorphic {
|
|
|
762
808
|
}
|
|
763
809
|
if (!defaultApplication) {
|
|
764
810
|
throw new MicrofrontendError(
|
|
765
|
-
|
|
811
|
+
"Could not find default application in microfrontends configuration",
|
|
766
812
|
{
|
|
767
813
|
type: "application",
|
|
768
814
|
subtype: "not_found"
|
|
@@ -1062,11 +1108,21 @@ var schema_default = {
|
|
|
1062
1108
|
properties: {
|
|
1063
1109
|
vercel: {
|
|
1064
1110
|
$ref: "#/definitions/VercelOptions",
|
|
1065
|
-
description: "
|
|
1111
|
+
description: "Microfrontends wide options for Vercel.",
|
|
1112
|
+
deprecated: "This is being replaced by the `disableOverrides` field below."
|
|
1113
|
+
},
|
|
1114
|
+
disableOverrides: {
|
|
1115
|
+
type: "boolean",
|
|
1116
|
+
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."
|
|
1066
1117
|
},
|
|
1067
1118
|
localProxy: {
|
|
1068
1119
|
$ref: "#/definitions/LocalProxyOptions",
|
|
1069
|
-
description: "Options for local proxy."
|
|
1120
|
+
description: "Options for local proxy.",
|
|
1121
|
+
deprecated: "This is being replaced by the `localProxyPort` field below."
|
|
1122
|
+
},
|
|
1123
|
+
localProxyPort: {
|
|
1124
|
+
type: "number",
|
|
1125
|
+
description: "The port number used by the local proxy server.\n\nThe default is `3024`."
|
|
1070
1126
|
}
|
|
1071
1127
|
},
|
|
1072
1128
|
additionalProperties: false
|
|
@@ -1114,13 +1170,19 @@ var schema_default = {
|
|
|
1114
1170
|
type: "object",
|
|
1115
1171
|
properties: {
|
|
1116
1172
|
vercel: {
|
|
1117
|
-
$ref: "#/definitions/Vercel"
|
|
1173
|
+
$ref: "#/definitions/Vercel",
|
|
1174
|
+
deprecated: "This is being replaced by the `projectId` field below."
|
|
1175
|
+
},
|
|
1176
|
+
projectId: {
|
|
1177
|
+
type: "string",
|
|
1178
|
+
description: "Vercel project ID"
|
|
1118
1179
|
},
|
|
1119
1180
|
development: {
|
|
1120
1181
|
$ref: "#/definitions/Development"
|
|
1121
1182
|
},
|
|
1122
1183
|
production: {
|
|
1123
|
-
$ref: "#/definitions/HostConfig"
|
|
1184
|
+
$ref: "#/definitions/HostConfig",
|
|
1185
|
+
deprecated: "This is a duplicate of the `development.fallback` field and this will be removed soon."
|
|
1124
1186
|
}
|
|
1125
1187
|
},
|
|
1126
1188
|
required: ["production"],
|
|
@@ -1141,11 +1203,23 @@ var schema_default = {
|
|
|
1141
1203
|
type: "object",
|
|
1142
1204
|
properties: {
|
|
1143
1205
|
local: {
|
|
1144
|
-
$ref: "#/definitions/LocalHostConfig"
|
|
1206
|
+
$ref: "#/definitions/LocalHostConfig",
|
|
1207
|
+
deprecated: "This is being replaced by the `localPort` field below."
|
|
1208
|
+
},
|
|
1209
|
+
localPort: {
|
|
1210
|
+
type: "number",
|
|
1211
|
+
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."
|
|
1145
1212
|
},
|
|
1146
1213
|
fallback: {
|
|
1147
|
-
|
|
1148
|
-
|
|
1214
|
+
anyOf: [
|
|
1215
|
+
{
|
|
1216
|
+
$ref: "#/definitions/HostConfig"
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
type: "string"
|
|
1220
|
+
}
|
|
1221
|
+
],
|
|
1222
|
+
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."
|
|
1149
1223
|
},
|
|
1150
1224
|
task: {
|
|
1151
1225
|
type: "string",
|
|
@@ -1197,7 +1271,12 @@ var schema_default = {
|
|
|
1197
1271
|
type: "object",
|
|
1198
1272
|
properties: {
|
|
1199
1273
|
vercel: {
|
|
1200
|
-
$ref: "#/definitions/Vercel"
|
|
1274
|
+
$ref: "#/definitions/Vercel",
|
|
1275
|
+
deprecated: "This is being replaced by the `projectId` field below."
|
|
1276
|
+
},
|
|
1277
|
+
projectId: {
|
|
1278
|
+
type: "string",
|
|
1279
|
+
description: "Vercel project ID"
|
|
1201
1280
|
},
|
|
1202
1281
|
development: {
|
|
1203
1282
|
$ref: "#/definitions/Development"
|
|
@@ -1207,7 +1286,8 @@ var schema_default = {
|
|
|
1207
1286
|
description: "Groups of path expressions that are routed to this application."
|
|
1208
1287
|
},
|
|
1209
1288
|
production: {
|
|
1210
|
-
$ref: "#/definitions/HostConfig"
|
|
1289
|
+
$ref: "#/definitions/HostConfig",
|
|
1290
|
+
deprecated: "This is a duplicate of the `development.fallback` field and this will be removed soon."
|
|
1211
1291
|
}
|
|
1212
1292
|
},
|
|
1213
1293
|
required: ["routing"],
|
|
@@ -1503,7 +1583,7 @@ var MicrofrontendsServer = class extends Microfrontends {
|
|
|
1503
1583
|
const [defaultApplication] = Object.entries(validatedConfig.applications).filter(([, app]) => isDefaultApp(app)).map(([name]) => name);
|
|
1504
1584
|
if (!defaultApplication) {
|
|
1505
1585
|
throw new MicrofrontendError(
|
|
1506
|
-
|
|
1586
|
+
"No default application found. At least one application needs to be the default by omitting routing.",
|
|
1507
1587
|
{ type: "config", subtype: "no_default_application" }
|
|
1508
1588
|
);
|
|
1509
1589
|
}
|