@vercel/microfrontends 2.2.1 → 2.2.2
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/CHANGELOG.md +19 -0
- package/cli/index.cjs +0 -1
- package/dist/bin/cli.cjs +483 -394
- package/dist/config.cjs +191 -169
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.ts +3 -2
- package/dist/config.js +192 -170
- package/dist/config.js.map +1 -1
- package/dist/experimental/sveltekit.cjs +583 -511
- package/dist/experimental/sveltekit.cjs.map +1 -1
- package/dist/experimental/sveltekit.js +589 -517
- package/dist/experimental/sveltekit.js.map +1 -1
- package/dist/experimental/vite.cjs +605 -533
- package/dist/experimental/vite.cjs.map +1 -1
- package/dist/experimental/vite.js +614 -542
- package/dist/experimental/vite.js.map +1 -1
- package/dist/microfrontends/server.cjs +601 -529
- package/dist/microfrontends/server.cjs.map +1 -1
- package/dist/microfrontends/server.d.ts +2 -2
- package/dist/microfrontends/server.js +607 -535
- package/dist/microfrontends/server.js.map +1 -1
- package/dist/microfrontends/utils.cjs +101 -50
- package/dist/microfrontends/utils.cjs.map +1 -1
- package/dist/microfrontends/utils.d.ts +4 -4
- package/dist/microfrontends/utils.js +102 -51
- package/dist/microfrontends/utils.js.map +1 -1
- package/dist/next/client.cjs +1 -1
- package/dist/next/client.cjs.map +1 -1
- package/dist/next/client.d.ts +8 -8
- package/dist/next/client.js +1 -1
- package/dist/next/client.js.map +1 -1
- package/dist/next/config.cjs +723 -647
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.js +720 -644
- package/dist/next/config.js.map +1 -1
- package/dist/next/middleware.cjs +244 -222
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.js +245 -223
- package/dist/next/middleware.js.map +1 -1
- package/dist/next/testing.cjs +192 -170
- package/dist/next/testing.cjs.map +1 -1
- package/dist/next/testing.d.ts +1 -1
- package/dist/next/testing.js +193 -171
- package/dist/next/testing.js.map +1 -1
- package/dist/overrides.cjs +5 -5
- package/dist/overrides.cjs.map +1 -1
- package/dist/overrides.d.ts +9 -9
- package/dist/overrides.js +5 -5
- package/dist/overrides.js.map +1 -1
- package/dist/utils/mfe-port.cjs +620 -533
- package/dist/utils/mfe-port.cjs.map +1 -1
- package/dist/utils/mfe-port.d.ts +9 -1
- package/dist/utils/mfe-port.js +632 -546
- package/dist/utils/mfe-port.js.map +1 -1
- package/dist/validation.cjs +8 -24
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.js +8 -24
- package/dist/validation.js.map +1 -1
- package/package.json +4 -6
package/dist/bin/cli.cjs
CHANGED
|
@@ -24,13 +24,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/bin/index.ts
|
|
27
|
-
var import_commander = require("commander");
|
|
28
27
|
var import_env = require("@next/env");
|
|
28
|
+
var import_commander = require("commander");
|
|
29
29
|
|
|
30
30
|
// package.json
|
|
31
31
|
var package_default = {
|
|
32
32
|
name: "@vercel/microfrontends",
|
|
33
|
-
version: "2.2.
|
|
33
|
+
version: "2.2.2",
|
|
34
34
|
private: false,
|
|
35
35
|
description: "Defines configuration and utilities for microfrontends development",
|
|
36
36
|
keywords: [
|
|
@@ -161,15 +161,14 @@ var package_default = {
|
|
|
161
161
|
postbuild: "pnpm generate:exports",
|
|
162
162
|
"generate:exports": "tsx scripts/generate-exports/index.ts",
|
|
163
163
|
"generate:schema": "tsx scripts/generate-json-schema.ts",
|
|
164
|
-
lint: "
|
|
165
|
-
"lint-fix": "eslint . --fix",
|
|
164
|
+
lint: "biome check",
|
|
166
165
|
prepublishOnly: "pnpm build && pnpm generate:exports && pnpm generate:schema",
|
|
167
166
|
proxy: "tsx src/proxy/index.ts",
|
|
168
167
|
test: "cross-env TZ=UTC jest",
|
|
169
168
|
typecheck: "tsc --noEmit"
|
|
170
169
|
},
|
|
171
170
|
dependencies: {
|
|
172
|
-
"@next/env": "
|
|
171
|
+
"@next/env": "16.0.10",
|
|
173
172
|
"@types/md5": "^2.3.5",
|
|
174
173
|
ajv: "^8.17.1",
|
|
175
174
|
commander: "^12.1.0",
|
|
@@ -195,10 +194,9 @@ var package_default = {
|
|
|
195
194
|
"@types/react": "18.3.1",
|
|
196
195
|
"@types/react-dom": "18.3.0",
|
|
197
196
|
"@types/semver": "^7.7.0",
|
|
198
|
-
"eslint-config-custom": "workspace:*",
|
|
199
197
|
jest: "^29.7.0",
|
|
200
198
|
"jest-environment-jsdom": "29.2.2",
|
|
201
|
-
next: "
|
|
199
|
+
next: "16.0.10",
|
|
202
200
|
react: "19.0.0",
|
|
203
201
|
"react-dom": "19.0.0",
|
|
204
202
|
"ts-config": "workspace:*",
|
|
@@ -249,11 +247,34 @@ var http = __toESM(require("http"), 1);
|
|
|
249
247
|
var https = __toESM(require("https"), 1);
|
|
250
248
|
var import_node_url = require("url");
|
|
251
249
|
var import_cookie = require("cookie");
|
|
252
|
-
var import_path_to_regexp3 = require("path-to-regexp");
|
|
253
250
|
var import_http_proxy = __toESM(require("http-proxy"), 1);
|
|
251
|
+
var import_path_to_regexp3 = require("path-to-regexp");
|
|
254
252
|
|
|
255
|
-
// src/config/microfrontends
|
|
256
|
-
var
|
|
253
|
+
// src/config/microfrontends/server/index.ts
|
|
254
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
255
|
+
var import_node_path8 = require("path");
|
|
256
|
+
|
|
257
|
+
// src/bin/logger.ts
|
|
258
|
+
function debug(...args) {
|
|
259
|
+
if (process.env.MFE_DEBUG) {
|
|
260
|
+
console.log(...args);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function info(...args) {
|
|
264
|
+
console.log(...args);
|
|
265
|
+
}
|
|
266
|
+
function warn(...args) {
|
|
267
|
+
console.warn(...args);
|
|
268
|
+
}
|
|
269
|
+
function error(...args) {
|
|
270
|
+
console.error(...args);
|
|
271
|
+
}
|
|
272
|
+
var logger = {
|
|
273
|
+
debug,
|
|
274
|
+
info,
|
|
275
|
+
warn,
|
|
276
|
+
error
|
|
277
|
+
};
|
|
257
278
|
|
|
258
279
|
// src/config/errors.ts
|
|
259
280
|
var MicrofrontendError = class extends Error {
|
|
@@ -347,27 +368,18 @@ var MicrofrontendError = class extends Error {
|
|
|
347
368
|
}
|
|
348
369
|
};
|
|
349
370
|
|
|
350
|
-
// src/config/microfrontends-config/
|
|
351
|
-
|
|
352
|
-
const config = process.env.MFE_CONFIG;
|
|
353
|
-
if (!config) {
|
|
354
|
-
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
355
|
-
type: "config",
|
|
356
|
-
subtype: "not_found_in_env"
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
return config;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// src/config/schema/utils/is-default-app.ts
|
|
363
|
-
function isDefaultApp(a) {
|
|
364
|
-
return !("routing" in a);
|
|
365
|
-
}
|
|
371
|
+
// src/config/microfrontends-config/isomorphic/index.ts
|
|
372
|
+
var import_jsonc_parser = require("jsonc-parser");
|
|
366
373
|
|
|
367
374
|
// src/config/overrides/constants.ts
|
|
368
375
|
var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
|
|
369
376
|
var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
370
377
|
|
|
378
|
+
// src/config/overrides/get-app-env-override-cookie-name.ts
|
|
379
|
+
function getAppEnvOverrideCookieName(application) {
|
|
380
|
+
return `${OVERRIDES_ENV_COOKIE_PREFIX}${application}`;
|
|
381
|
+
}
|
|
382
|
+
|
|
371
383
|
// src/config/overrides/is-override-cookie.ts
|
|
372
384
|
function isOverrideCookie(cookie) {
|
|
373
385
|
return Boolean(cookie.name?.startsWith(OVERRIDES_COOKIE_PREFIX));
|
|
@@ -397,9 +409,9 @@ function parseOverrides(cookies) {
|
|
|
397
409
|
return overridesConfig;
|
|
398
410
|
}
|
|
399
411
|
|
|
400
|
-
// src/config/
|
|
401
|
-
function
|
|
402
|
-
return
|
|
412
|
+
// src/config/schema/utils/is-default-app.ts
|
|
413
|
+
function isDefaultApp(a) {
|
|
414
|
+
return !("routing" in a);
|
|
403
415
|
}
|
|
404
416
|
|
|
405
417
|
// src/config/microfrontends-config/client/index.ts
|
|
@@ -500,6 +512,183 @@ var MicrofrontendConfigClient = class {
|
|
|
500
512
|
}
|
|
501
513
|
};
|
|
502
514
|
|
|
515
|
+
// src/config/microfrontends-config/utils/get-config-from-env.ts
|
|
516
|
+
function getConfigStringFromEnv() {
|
|
517
|
+
const config = process.env.MFE_CONFIG;
|
|
518
|
+
if (!config) {
|
|
519
|
+
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
520
|
+
type: "config",
|
|
521
|
+
subtype: "not_found_in_env"
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
return config;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// src/config/microfrontends-config/isomorphic/constants.ts
|
|
528
|
+
var DEFAULT_LOCAL_PROXY_PORT = 3024;
|
|
529
|
+
var MFE_APP_PORT_ENV = "MFE_APP_PORT";
|
|
530
|
+
var MFE_LOCAL_PROXY_PORT_ENV = "MFE_LOCAL_PROXY_PORT";
|
|
531
|
+
|
|
532
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-port.ts
|
|
533
|
+
function generatePortFromName({
|
|
534
|
+
name,
|
|
535
|
+
minPort = 3e3,
|
|
536
|
+
maxPort = 8e3
|
|
537
|
+
}) {
|
|
538
|
+
if (!name) {
|
|
539
|
+
throw new Error("Name is required to generate a port");
|
|
540
|
+
}
|
|
541
|
+
let hash = 0;
|
|
542
|
+
for (let i = 0; i < name.length; i++) {
|
|
543
|
+
hash = (hash << 5) - hash + name.charCodeAt(i);
|
|
544
|
+
hash |= 0;
|
|
545
|
+
}
|
|
546
|
+
hash = Math.abs(hash);
|
|
547
|
+
const range = maxPort - minPort;
|
|
548
|
+
const port = minPort + hash % range;
|
|
549
|
+
return port;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// src/config/microfrontends-config/isomorphic/host.ts
|
|
553
|
+
var Host = class {
|
|
554
|
+
constructor(hostConfig, options) {
|
|
555
|
+
if (typeof hostConfig === "string") {
|
|
556
|
+
({
|
|
557
|
+
protocol: this.protocol,
|
|
558
|
+
host: this.host,
|
|
559
|
+
port: this.port
|
|
560
|
+
} = Host.parseUrl(hostConfig));
|
|
561
|
+
} else {
|
|
562
|
+
const { protocol = "https", host, port } = hostConfig;
|
|
563
|
+
this.protocol = protocol;
|
|
564
|
+
this.host = host;
|
|
565
|
+
this.port = port;
|
|
566
|
+
}
|
|
567
|
+
this.local = options?.isLocal;
|
|
568
|
+
}
|
|
569
|
+
static parseUrl(url, defaultProtocol = "https") {
|
|
570
|
+
let hostToParse = url;
|
|
571
|
+
if (!/^https?:\/\//.exec(hostToParse)) {
|
|
572
|
+
hostToParse = `${defaultProtocol}://${hostToParse}`;
|
|
573
|
+
}
|
|
574
|
+
const parsed = new URL(hostToParse);
|
|
575
|
+
if (!parsed.hostname) {
|
|
576
|
+
throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
|
|
577
|
+
}
|
|
578
|
+
if (parsed.hash) {
|
|
579
|
+
throw new Error(
|
|
580
|
+
Host.getMicrofrontendsError(url, "cannot have a fragment")
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
if (parsed.username || parsed.password) {
|
|
584
|
+
throw new Error(
|
|
585
|
+
Host.getMicrofrontendsError(
|
|
586
|
+
url,
|
|
587
|
+
"cannot have authentication credentials (username and/or password)"
|
|
588
|
+
)
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
if (parsed.pathname !== "/") {
|
|
592
|
+
throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
|
|
593
|
+
}
|
|
594
|
+
if (parsed.search) {
|
|
595
|
+
throw new Error(
|
|
596
|
+
Host.getMicrofrontendsError(url, "cannot have query parameters")
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
const protocol = parsed.protocol.slice(0, -1);
|
|
600
|
+
return {
|
|
601
|
+
protocol,
|
|
602
|
+
host: parsed.hostname,
|
|
603
|
+
port: parsed.port ? Number.parseInt(parsed.port, 10) : void 0
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
static getMicrofrontendsError(url, message) {
|
|
607
|
+
return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
|
|
608
|
+
}
|
|
609
|
+
isLocal() {
|
|
610
|
+
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
611
|
+
}
|
|
612
|
+
toString() {
|
|
613
|
+
const url = this.toUrl();
|
|
614
|
+
return url.toString().replace(/\/$/, "");
|
|
615
|
+
}
|
|
616
|
+
toUrl() {
|
|
617
|
+
const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
|
|
618
|
+
return new URL(url);
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
var LocalHost = class extends Host {
|
|
622
|
+
constructor({
|
|
623
|
+
appName,
|
|
624
|
+
local
|
|
625
|
+
}) {
|
|
626
|
+
const portOverride = process.env[MFE_APP_PORT_ENV];
|
|
627
|
+
if (portOverride) {
|
|
628
|
+
const overridePort = Number.parseInt(portOverride, 10);
|
|
629
|
+
if (!Number.isNaN(overridePort) && overridePort > 0 && overridePort < 65536) {
|
|
630
|
+
super({
|
|
631
|
+
protocol: "http",
|
|
632
|
+
host: "localhost",
|
|
633
|
+
port: overridePort
|
|
634
|
+
});
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
let protocol;
|
|
639
|
+
let host;
|
|
640
|
+
let port;
|
|
641
|
+
if (typeof local === "number") {
|
|
642
|
+
port = local;
|
|
643
|
+
} else if (typeof local === "string") {
|
|
644
|
+
if (/^\d+$/.test(local)) {
|
|
645
|
+
port = Number.parseInt(local, 10);
|
|
646
|
+
} else {
|
|
647
|
+
const parsed = Host.parseUrl(local, "http");
|
|
648
|
+
protocol = parsed.protocol;
|
|
649
|
+
host = parsed.host;
|
|
650
|
+
port = parsed.port;
|
|
651
|
+
}
|
|
652
|
+
} else if (local) {
|
|
653
|
+
protocol = local.protocol;
|
|
654
|
+
host = local.host;
|
|
655
|
+
port = local.port;
|
|
656
|
+
}
|
|
657
|
+
super({
|
|
658
|
+
protocol: protocol ?? "http",
|
|
659
|
+
host: host ?? "localhost",
|
|
660
|
+
port: port ?? generatePortFromName({ name: appName })
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
// src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts
|
|
666
|
+
var import_md5 = __toESM(require("md5"), 1);
|
|
667
|
+
function hashApplicationName(name) {
|
|
668
|
+
if (!name) {
|
|
669
|
+
throw new Error("Application name is required to generate hash");
|
|
670
|
+
}
|
|
671
|
+
return (0, import_md5.default)(name).substring(0, 6).padStart(6, "0");
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
|
|
675
|
+
var PREFIX = "vc-ap";
|
|
676
|
+
function generateAssetPrefixFromName({
|
|
677
|
+
name
|
|
678
|
+
}) {
|
|
679
|
+
if (!name) {
|
|
680
|
+
throw new Error("Name is required to generate an asset prefix");
|
|
681
|
+
}
|
|
682
|
+
return `${PREFIX}-${hashApplicationName(name)}`;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts
|
|
686
|
+
function generateAutomationBypassEnvVarName({
|
|
687
|
+
name
|
|
688
|
+
}) {
|
|
689
|
+
return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
690
|
+
}
|
|
691
|
+
|
|
503
692
|
// src/config/microfrontends-config/isomorphic/validation.ts
|
|
504
693
|
var import_path_to_regexp2 = require("path-to-regexp");
|
|
505
694
|
var LIST_FORMATTER = new Intl.ListFormat("en", {
|
|
@@ -681,154 +870,6 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
|
|
|
681
870
|
}
|
|
682
871
|
};
|
|
683
872
|
|
|
684
|
-
// src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts
|
|
685
|
-
var import_md5 = __toESM(require("md5"), 1);
|
|
686
|
-
function hashApplicationName(name) {
|
|
687
|
-
if (!name) {
|
|
688
|
-
throw new Error("Application name is required to generate hash");
|
|
689
|
-
}
|
|
690
|
-
return (0, import_md5.default)(name).substring(0, 6).padStart(6, "0");
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
// src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
|
|
694
|
-
var PREFIX = "vc-ap";
|
|
695
|
-
function generateAssetPrefixFromName({
|
|
696
|
-
name
|
|
697
|
-
}) {
|
|
698
|
-
if (!name) {
|
|
699
|
-
throw new Error("Name is required to generate an asset prefix");
|
|
700
|
-
}
|
|
701
|
-
return `${PREFIX}-${hashApplicationName(name)}`;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// src/config/microfrontends-config/isomorphic/utils/generate-port.ts
|
|
705
|
-
function generatePortFromName({
|
|
706
|
-
name,
|
|
707
|
-
minPort = 3e3,
|
|
708
|
-
maxPort = 8e3
|
|
709
|
-
}) {
|
|
710
|
-
if (!name) {
|
|
711
|
-
throw new Error("Name is required to generate a port");
|
|
712
|
-
}
|
|
713
|
-
let hash = 0;
|
|
714
|
-
for (let i = 0; i < name.length; i++) {
|
|
715
|
-
hash = (hash << 5) - hash + name.charCodeAt(i);
|
|
716
|
-
hash |= 0;
|
|
717
|
-
}
|
|
718
|
-
hash = Math.abs(hash);
|
|
719
|
-
const range = maxPort - minPort;
|
|
720
|
-
const port = minPort + hash % range;
|
|
721
|
-
return port;
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
// src/config/microfrontends-config/isomorphic/host.ts
|
|
725
|
-
var Host = class {
|
|
726
|
-
constructor(hostConfig, options) {
|
|
727
|
-
if (typeof hostConfig === "string") {
|
|
728
|
-
({
|
|
729
|
-
protocol: this.protocol,
|
|
730
|
-
host: this.host,
|
|
731
|
-
port: this.port
|
|
732
|
-
} = Host.parseUrl(hostConfig));
|
|
733
|
-
} else {
|
|
734
|
-
const { protocol = "https", host, port } = hostConfig;
|
|
735
|
-
this.protocol = protocol;
|
|
736
|
-
this.host = host;
|
|
737
|
-
this.port = port;
|
|
738
|
-
}
|
|
739
|
-
this.local = options?.isLocal;
|
|
740
|
-
}
|
|
741
|
-
static parseUrl(url, defaultProtocol = "https") {
|
|
742
|
-
let hostToParse = url;
|
|
743
|
-
if (!/^https?:\/\//.exec(hostToParse)) {
|
|
744
|
-
hostToParse = `${defaultProtocol}://${hostToParse}`;
|
|
745
|
-
}
|
|
746
|
-
const parsed = new URL(hostToParse);
|
|
747
|
-
if (!parsed.hostname) {
|
|
748
|
-
throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
|
|
749
|
-
}
|
|
750
|
-
if (parsed.hash) {
|
|
751
|
-
throw new Error(
|
|
752
|
-
Host.getMicrofrontendsError(url, "cannot have a fragment")
|
|
753
|
-
);
|
|
754
|
-
}
|
|
755
|
-
if (parsed.username || parsed.password) {
|
|
756
|
-
throw new Error(
|
|
757
|
-
Host.getMicrofrontendsError(
|
|
758
|
-
url,
|
|
759
|
-
"cannot have authentication credentials (username and/or password)"
|
|
760
|
-
)
|
|
761
|
-
);
|
|
762
|
-
}
|
|
763
|
-
if (parsed.pathname !== "/") {
|
|
764
|
-
throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
|
|
765
|
-
}
|
|
766
|
-
if (parsed.search) {
|
|
767
|
-
throw new Error(
|
|
768
|
-
Host.getMicrofrontendsError(url, "cannot have query parameters")
|
|
769
|
-
);
|
|
770
|
-
}
|
|
771
|
-
const protocol = parsed.protocol.slice(0, -1);
|
|
772
|
-
return {
|
|
773
|
-
protocol,
|
|
774
|
-
host: parsed.hostname,
|
|
775
|
-
port: parsed.port ? Number.parseInt(parsed.port) : void 0
|
|
776
|
-
};
|
|
777
|
-
}
|
|
778
|
-
static getMicrofrontendsError(url, message) {
|
|
779
|
-
return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
|
|
780
|
-
}
|
|
781
|
-
isLocal() {
|
|
782
|
-
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
783
|
-
}
|
|
784
|
-
toString() {
|
|
785
|
-
const url = this.toUrl();
|
|
786
|
-
return url.toString().replace(/\/$/, "");
|
|
787
|
-
}
|
|
788
|
-
toUrl() {
|
|
789
|
-
const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
|
|
790
|
-
return new URL(url);
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
var LocalHost = class extends Host {
|
|
794
|
-
constructor({
|
|
795
|
-
appName,
|
|
796
|
-
local
|
|
797
|
-
}) {
|
|
798
|
-
let protocol;
|
|
799
|
-
let host;
|
|
800
|
-
let port;
|
|
801
|
-
if (typeof local === "number") {
|
|
802
|
-
port = local;
|
|
803
|
-
} else if (typeof local === "string") {
|
|
804
|
-
if (/^\d+$/.test(local)) {
|
|
805
|
-
port = Number.parseInt(local);
|
|
806
|
-
} else {
|
|
807
|
-
const parsed = Host.parseUrl(local, "http");
|
|
808
|
-
protocol = parsed.protocol;
|
|
809
|
-
host = parsed.host;
|
|
810
|
-
port = parsed.port;
|
|
811
|
-
}
|
|
812
|
-
} else if (local) {
|
|
813
|
-
protocol = local.protocol;
|
|
814
|
-
host = local.host;
|
|
815
|
-
port = local.port;
|
|
816
|
-
}
|
|
817
|
-
super({
|
|
818
|
-
protocol: protocol ?? "http",
|
|
819
|
-
host: host ?? "localhost",
|
|
820
|
-
port: port ?? generatePortFromName({ name: appName })
|
|
821
|
-
});
|
|
822
|
-
}
|
|
823
|
-
};
|
|
824
|
-
|
|
825
|
-
// src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts
|
|
826
|
-
function generateAutomationBypassEnvVarName({
|
|
827
|
-
name
|
|
828
|
-
}) {
|
|
829
|
-
return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
873
|
// src/config/microfrontends-config/isomorphic/application.ts
|
|
833
874
|
var Application = class {
|
|
834
875
|
constructor(name, {
|
|
@@ -909,9 +950,6 @@ var ChildApplication = class extends Application {
|
|
|
909
950
|
}
|
|
910
951
|
};
|
|
911
952
|
|
|
912
|
-
// src/config/microfrontends-config/isomorphic/constants.ts
|
|
913
|
-
var DEFAULT_LOCAL_PROXY_PORT = 3024;
|
|
914
|
-
|
|
915
953
|
// src/config/microfrontends-config/isomorphic/index.ts
|
|
916
954
|
var MicrofrontendConfigIsomorphic = class {
|
|
917
955
|
constructor({
|
|
@@ -1030,9 +1068,17 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
1030
1068
|
return this.defaultApplication;
|
|
1031
1069
|
}
|
|
1032
1070
|
/**
|
|
1033
|
-
* Returns the configured port for the local proxy
|
|
1071
|
+
* Returns the configured port for the local proxy.
|
|
1072
|
+
* Can be overridden via MFE_LOCAL_PROXY_PORT environment variable.
|
|
1034
1073
|
*/
|
|
1035
1074
|
getLocalProxyPort() {
|
|
1075
|
+
const portOverride = process.env[MFE_LOCAL_PROXY_PORT_ENV];
|
|
1076
|
+
if (portOverride) {
|
|
1077
|
+
const port = Number.parseInt(portOverride, 10);
|
|
1078
|
+
if (!Number.isNaN(port) && port > 0 && port < 65536) {
|
|
1079
|
+
return port;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1036
1082
|
return this.config.options?.localProxyPort ?? DEFAULT_LOCAL_PROXY_PORT;
|
|
1037
1083
|
}
|
|
1038
1084
|
toClientConfig(options) {
|
|
@@ -1070,23 +1116,78 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
1070
1116
|
}
|
|
1071
1117
|
};
|
|
1072
1118
|
|
|
1073
|
-
// src/config/microfrontends/
|
|
1074
|
-
var
|
|
1075
|
-
var
|
|
1119
|
+
// src/config/microfrontends/utils/find-config.ts
|
|
1120
|
+
var import_node_fs = __toESM(require("fs"), 1);
|
|
1121
|
+
var import_node_path = require("path");
|
|
1122
|
+
|
|
1123
|
+
// src/config/microfrontends/utils/get-config-file-name.ts
|
|
1124
|
+
var DEFAULT_CONFIGURATION_FILENAMES = [
|
|
1125
|
+
"microfrontends.json",
|
|
1126
|
+
"microfrontends.jsonc"
|
|
1127
|
+
];
|
|
1128
|
+
function getPossibleConfigurationFilenames({
|
|
1129
|
+
customConfigFilename
|
|
1130
|
+
}) {
|
|
1131
|
+
if (customConfigFilename) {
|
|
1132
|
+
if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
|
|
1133
|
+
throw new Error(
|
|
1134
|
+
`Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}. The file name must end with '.json' or '.jsonc'. It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
return Array.from(
|
|
1138
|
+
/* @__PURE__ */ new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES])
|
|
1139
|
+
);
|
|
1140
|
+
}
|
|
1141
|
+
return DEFAULT_CONFIGURATION_FILENAMES;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
// src/config/microfrontends/utils/find-config.ts
|
|
1145
|
+
function findConfig({
|
|
1146
|
+
dir,
|
|
1147
|
+
customConfigFilename
|
|
1148
|
+
}) {
|
|
1149
|
+
for (const filename of getPossibleConfigurationFilenames({
|
|
1150
|
+
customConfigFilename
|
|
1151
|
+
})) {
|
|
1152
|
+
const maybeConfig = (0, import_node_path.join)(dir, filename);
|
|
1153
|
+
if (import_node_fs.default.existsSync(maybeConfig)) {
|
|
1154
|
+
return maybeConfig;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
return null;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
// src/config/microfrontends/utils/find-package-root.ts
|
|
1161
|
+
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
1162
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
1163
|
+
var PACKAGE_JSON = "package.json";
|
|
1164
|
+
function findPackageRoot(startDir) {
|
|
1165
|
+
let currentDir = startDir || process.cwd();
|
|
1166
|
+
while (currentDir !== import_node_path2.default.parse(currentDir).root) {
|
|
1167
|
+
const pkgJsonPath = import_node_path2.default.join(currentDir, PACKAGE_JSON);
|
|
1168
|
+
if (import_node_fs2.default.existsSync(pkgJsonPath)) {
|
|
1169
|
+
return currentDir;
|
|
1170
|
+
}
|
|
1171
|
+
currentDir = import_node_path2.default.dirname(currentDir);
|
|
1172
|
+
}
|
|
1173
|
+
throw new Error(
|
|
1174
|
+
`The root of the package that contains the \`package.json\` file for the \`${startDir}\` directory could not be found.`
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1076
1177
|
|
|
1077
1178
|
// src/config/microfrontends/utils/find-repository-root.ts
|
|
1078
|
-
var
|
|
1079
|
-
var
|
|
1179
|
+
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
1180
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
1080
1181
|
var GIT_DIRECTORY = ".git";
|
|
1081
1182
|
function hasGitDirectory(dir) {
|
|
1082
|
-
const gitPath =
|
|
1083
|
-
return
|
|
1183
|
+
const gitPath = import_node_path3.default.join(dir, GIT_DIRECTORY);
|
|
1184
|
+
return import_node_fs3.default.existsSync(gitPath) && import_node_fs3.default.statSync(gitPath).isDirectory();
|
|
1084
1185
|
}
|
|
1085
1186
|
function hasPnpmWorkspaces(dir) {
|
|
1086
|
-
return
|
|
1187
|
+
return import_node_fs3.default.existsSync(import_node_path3.default.join(dir, "pnpm-workspace.yaml"));
|
|
1087
1188
|
}
|
|
1088
1189
|
function hasPackageJson(dir) {
|
|
1089
|
-
return
|
|
1190
|
+
return import_node_fs3.default.existsSync(import_node_path3.default.join(dir, "package.json"));
|
|
1090
1191
|
}
|
|
1091
1192
|
function findRepositoryRoot(startDir) {
|
|
1092
1193
|
if (process.env.NX_WORKSPACE_ROOT) {
|
|
@@ -1094,14 +1195,14 @@ function findRepositoryRoot(startDir) {
|
|
|
1094
1195
|
}
|
|
1095
1196
|
let currentDir = startDir || process.cwd();
|
|
1096
1197
|
let lastPackageJsonDir = null;
|
|
1097
|
-
while (currentDir !==
|
|
1198
|
+
while (currentDir !== import_node_path3.default.parse(currentDir).root) {
|
|
1098
1199
|
if (hasGitDirectory(currentDir) || hasPnpmWorkspaces(currentDir)) {
|
|
1099
1200
|
return currentDir;
|
|
1100
1201
|
}
|
|
1101
1202
|
if (hasPackageJson(currentDir)) {
|
|
1102
1203
|
lastPackageJsonDir = currentDir;
|
|
1103
1204
|
}
|
|
1104
|
-
currentDir =
|
|
1205
|
+
currentDir = import_node_path3.default.dirname(currentDir);
|
|
1105
1206
|
}
|
|
1106
1207
|
if (lastPackageJsonDir) {
|
|
1107
1208
|
return lastPackageJsonDir;
|
|
@@ -1111,56 +1212,88 @@ function findRepositoryRoot(startDir) {
|
|
|
1111
1212
|
);
|
|
1112
1213
|
}
|
|
1113
1214
|
|
|
1114
|
-
// src/config/microfrontends/utils/
|
|
1115
|
-
var
|
|
1116
|
-
var
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1215
|
+
// src/config/microfrontends/utils/get-application-context.ts
|
|
1216
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
1217
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
1218
|
+
function getApplicationContext(opts) {
|
|
1219
|
+
if (opts?.appName) {
|
|
1220
|
+
logger.debug(
|
|
1221
|
+
"[MFE Config] Application name from appName parameter:",
|
|
1222
|
+
opts.appName
|
|
1223
|
+
);
|
|
1224
|
+
return { name: opts.appName };
|
|
1124
1225
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
if (
|
|
1152
|
-
|
|
1153
|
-
|
|
1226
|
+
if (process.env.VERCEL_PROJECT_NAME) {
|
|
1227
|
+
logger.debug(
|
|
1228
|
+
"[MFE Config] Application name from VERCEL_PROJECT_NAME:",
|
|
1229
|
+
process.env.VERCEL_PROJECT_NAME
|
|
1230
|
+
);
|
|
1231
|
+
return {
|
|
1232
|
+
name: process.env.VERCEL_PROJECT_NAME,
|
|
1233
|
+
projectName: process.env.VERCEL_PROJECT_NAME
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1236
|
+
if (process.env.NX_TASK_TARGET_PROJECT) {
|
|
1237
|
+
logger.debug(
|
|
1238
|
+
"[MFE Config] Application name from NX_TASK_TARGET_PROJECT:",
|
|
1239
|
+
process.env.NX_TASK_TARGET_PROJECT
|
|
1240
|
+
);
|
|
1241
|
+
return {
|
|
1242
|
+
name: process.env.NX_TASK_TARGET_PROJECT,
|
|
1243
|
+
packageJsonName: process.env.NX_TASK_TARGET_PROJECT
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
try {
|
|
1247
|
+
const vercelProjectJsonPath = import_node_fs4.default.readFileSync(
|
|
1248
|
+
import_node_path4.default.join(opts?.packageRoot || ".", ".vercel", "project.json"),
|
|
1249
|
+
"utf-8"
|
|
1250
|
+
);
|
|
1251
|
+
const projectJson = JSON.parse(vercelProjectJsonPath);
|
|
1252
|
+
if (projectJson.projectName) {
|
|
1253
|
+
logger.debug(
|
|
1254
|
+
"[MFE Config] Application name from .vercel/project.json:",
|
|
1255
|
+
projectJson.projectName
|
|
1154
1256
|
);
|
|
1257
|
+
return {
|
|
1258
|
+
name: projectJson.projectName,
|
|
1259
|
+
projectName: projectJson.projectName
|
|
1260
|
+
};
|
|
1155
1261
|
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1262
|
+
} catch (_) {
|
|
1263
|
+
}
|
|
1264
|
+
try {
|
|
1265
|
+
const packageJsonString = import_node_fs4.default.readFileSync(
|
|
1266
|
+
import_node_path4.default.join(opts?.packageRoot || ".", "package.json"),
|
|
1267
|
+
"utf-8"
|
|
1268
|
+
);
|
|
1269
|
+
const packageJson = JSON.parse(packageJsonString);
|
|
1270
|
+
if (!packageJson.name) {
|
|
1271
|
+
throw new MicrofrontendError(
|
|
1272
|
+
`package.json file missing required field "name"`,
|
|
1273
|
+
{
|
|
1274
|
+
type: "packageJson",
|
|
1275
|
+
subtype: "missing_field_name",
|
|
1276
|
+
source: "@vercel/microfrontends/next"
|
|
1277
|
+
}
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
logger.debug(
|
|
1281
|
+
"[MFE Config] Application name from package.json:",
|
|
1282
|
+
packageJson.name
|
|
1158
1283
|
);
|
|
1284
|
+
return { name: packageJson.name, packageJsonName: packageJson.name };
|
|
1285
|
+
} catch (err) {
|
|
1286
|
+
throw MicrofrontendError.handle(err, {
|
|
1287
|
+
fileName: "package.json"
|
|
1288
|
+
});
|
|
1159
1289
|
}
|
|
1160
|
-
return DEFAULT_CONFIGURATION_FILENAMES;
|
|
1161
1290
|
}
|
|
1162
1291
|
|
|
1163
1292
|
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
1293
|
+
var import_node_fs5 = require("fs");
|
|
1294
|
+
var import_node_path5 = require("path");
|
|
1295
|
+
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
1296
|
+
var import_jsonc_parser2 = require("jsonc-parser");
|
|
1164
1297
|
var configCache = {};
|
|
1165
1298
|
function findPackageWithMicrofrontendsConfig({
|
|
1166
1299
|
repositoryRoot,
|
|
@@ -1190,32 +1323,8 @@ function findPackageWithMicrofrontendsConfig({
|
|
|
1190
1323
|
);
|
|
1191
1324
|
const matchingPaths = [];
|
|
1192
1325
|
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
microfrontendsJsonPath,
|
|
1196
|
-
"utf-8"
|
|
1197
|
-
);
|
|
1198
|
-
const microfrontendsJson = (0, import_jsonc_parser2.parse)(microfrontendsJsonContent);
|
|
1199
|
-
if (microfrontendsJson.applications[applicationName]) {
|
|
1200
|
-
logger.debug(
|
|
1201
|
-
"[MFE Config] Found application in config:",
|
|
1202
|
-
microfrontendsJsonPath
|
|
1203
|
-
);
|
|
1204
|
-
matchingPaths.push(microfrontendsJsonPath);
|
|
1205
|
-
} else {
|
|
1206
|
-
for (const [_, app] of Object.entries(
|
|
1207
|
-
microfrontendsJson.applications
|
|
1208
|
-
)) {
|
|
1209
|
-
if (app.packageName === applicationName) {
|
|
1210
|
-
logger.debug(
|
|
1211
|
-
"[MFE Config] Found application via packageName in config:",
|
|
1212
|
-
microfrontendsJsonPath
|
|
1213
|
-
);
|
|
1214
|
-
matchingPaths.push(microfrontendsJsonPath);
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
} catch (error2) {
|
|
1326
|
+
if (doesApplicationExistInConfig(microfrontendsJsonPath, applicationName)) {
|
|
1327
|
+
matchingPaths.push(microfrontendsJsonPath);
|
|
1219
1328
|
}
|
|
1220
1329
|
}
|
|
1221
1330
|
logger.debug(
|
|
@@ -1230,6 +1339,34 @@ ${matchingPaths.join("\n \u2022 ")}`,
|
|
|
1230
1339
|
);
|
|
1231
1340
|
}
|
|
1232
1341
|
if (matchingPaths.length === 0) {
|
|
1342
|
+
if (repositoryRoot && doesMisplacedConfigExist(
|
|
1343
|
+
repositoryRoot,
|
|
1344
|
+
applicationName,
|
|
1345
|
+
customConfigFilename
|
|
1346
|
+
)) {
|
|
1347
|
+
logger.debug(
|
|
1348
|
+
"[MFE Config] Found misplaced config in wrong .vercel directory in repository"
|
|
1349
|
+
);
|
|
1350
|
+
const misplacedConfigPath = (0, import_node_path5.join)(
|
|
1351
|
+
repositoryRoot,
|
|
1352
|
+
".vercel",
|
|
1353
|
+
customConfigFilename || "microfrontends.json"
|
|
1354
|
+
);
|
|
1355
|
+
throw new MicrofrontendError(
|
|
1356
|
+
`Unable to automatically infer the location of the \`microfrontends.json\` file.
|
|
1357
|
+
|
|
1358
|
+
A microfrontends config was found in the \`.vercel\` directory at the repository root: ${misplacedConfigPath}
|
|
1359
|
+
However, in a monorepo, the config file should be placed in the \`.vercel\` directory in your application directory instead.
|
|
1360
|
+
|
|
1361
|
+
To fix this:
|
|
1362
|
+
1. If using \`vercel link\`, run it with \`vercel link --repo\` to handle monorepos, or run \`vercel microfrontends pull --cwd=<application-directory>\` to make sure it pulls the \`microfrontends.json\` file to the correct location
|
|
1363
|
+
2. If manually defined, move the config file to the \`.vercel\` directory in your application
|
|
1364
|
+
3. Alternatively, set the VC_MICROFRONTENDS_CONFIG environment variable to the correct path
|
|
1365
|
+
|
|
1366
|
+
For more information, see: https://vercel.com/docs/cli/project-linking`,
|
|
1367
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1368
|
+
);
|
|
1369
|
+
}
|
|
1233
1370
|
let additionalErrorMessage = "";
|
|
1234
1371
|
if (microfrontendsJsonPaths.length > 0) {
|
|
1235
1372
|
if (!applicationContext.projectName) {
|
|
@@ -1254,7 +1391,7 @@ If you suspect this is thrown in error, please reach out to the Vercel team.`,
|
|
|
1254
1391
|
);
|
|
1255
1392
|
}
|
|
1256
1393
|
const [packageJsonPath] = matchingPaths;
|
|
1257
|
-
return (0,
|
|
1394
|
+
return (0, import_node_path5.dirname)(packageJsonPath);
|
|
1258
1395
|
} catch (error2) {
|
|
1259
1396
|
if (error2 instanceof MicrofrontendError) {
|
|
1260
1397
|
throw error2;
|
|
@@ -1277,29 +1414,76 @@ function inferMicrofrontendsLocation(opts) {
|
|
|
1277
1414
|
configCache[cacheKey] = result;
|
|
1278
1415
|
return result;
|
|
1279
1416
|
}
|
|
1417
|
+
function existsSync(path7) {
|
|
1418
|
+
try {
|
|
1419
|
+
(0, import_node_fs5.statSync)(path7);
|
|
1420
|
+
return true;
|
|
1421
|
+
} catch (_) {
|
|
1422
|
+
return false;
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
function doesMisplacedConfigExist(repositoryRoot, applicationName, customConfigFilename) {
|
|
1426
|
+
logger.debug(
|
|
1427
|
+
"[MFE Config] Looking for misplaced config in wrong .vercel directory"
|
|
1428
|
+
);
|
|
1429
|
+
const misplacedConfigPath = (0, import_node_path5.join)(
|
|
1430
|
+
repositoryRoot,
|
|
1431
|
+
".vercel",
|
|
1432
|
+
customConfigFilename || "microfrontends.json"
|
|
1433
|
+
);
|
|
1434
|
+
return existsSync(misplacedConfigPath) && doesApplicationExistInConfig(misplacedConfigPath, applicationName);
|
|
1435
|
+
}
|
|
1436
|
+
function doesApplicationExistInConfig(microfrontendsJsonPath, applicationName) {
|
|
1437
|
+
try {
|
|
1438
|
+
const microfrontendsJsonContent = (0, import_node_fs5.readFileSync)(
|
|
1439
|
+
microfrontendsJsonPath,
|
|
1440
|
+
"utf-8"
|
|
1441
|
+
);
|
|
1442
|
+
const microfrontendsJson = (0, import_jsonc_parser2.parse)(microfrontendsJsonContent);
|
|
1443
|
+
if (microfrontendsJson.applications[applicationName]) {
|
|
1444
|
+
logger.debug(
|
|
1445
|
+
"[MFE Config] Found application in config:",
|
|
1446
|
+
microfrontendsJsonPath
|
|
1447
|
+
);
|
|
1448
|
+
return true;
|
|
1449
|
+
}
|
|
1450
|
+
for (const [_, app] of Object.entries(microfrontendsJson.applications)) {
|
|
1451
|
+
if (app.packageName === applicationName) {
|
|
1452
|
+
logger.debug(
|
|
1453
|
+
"[MFE Config] Found application via packageName in config:",
|
|
1454
|
+
microfrontendsJsonPath
|
|
1455
|
+
);
|
|
1456
|
+
return true;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
} catch (error2) {
|
|
1460
|
+
logger.debug("[MFE Config] Error checking application in config:", error2);
|
|
1461
|
+
}
|
|
1462
|
+
return false;
|
|
1463
|
+
}
|
|
1280
1464
|
|
|
1281
1465
|
// src/config/microfrontends/utils/is-monorepo.ts
|
|
1282
|
-
var
|
|
1283
|
-
var
|
|
1466
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
1467
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
1284
1468
|
function isMonorepo({
|
|
1285
1469
|
repositoryRoot
|
|
1286
1470
|
}) {
|
|
1287
1471
|
try {
|
|
1288
|
-
if (
|
|
1472
|
+
if (import_node_fs6.default.existsSync(import_node_path6.default.join(repositoryRoot, "pnpm-workspace.yaml"))) {
|
|
1289
1473
|
return true;
|
|
1290
1474
|
}
|
|
1291
|
-
if (
|
|
1475
|
+
if (import_node_fs6.default.existsSync(import_node_path6.default.join(repositoryRoot, "vlt-workspaces.json"))) {
|
|
1292
1476
|
return true;
|
|
1293
1477
|
}
|
|
1294
|
-
if (process.env.NX_WORKSPACE_ROOT ===
|
|
1478
|
+
if (process.env.NX_WORKSPACE_ROOT === import_node_path6.default.resolve(repositoryRoot)) {
|
|
1295
1479
|
return true;
|
|
1296
1480
|
}
|
|
1297
|
-
const packageJsonPath =
|
|
1298
|
-
if (!
|
|
1481
|
+
const packageJsonPath = import_node_path6.default.join(repositoryRoot, "package.json");
|
|
1482
|
+
if (!import_node_fs6.default.existsSync(packageJsonPath)) {
|
|
1299
1483
|
return false;
|
|
1300
1484
|
}
|
|
1301
1485
|
const packageJson = JSON.parse(
|
|
1302
|
-
|
|
1486
|
+
import_node_fs6.default.readFileSync(packageJsonPath, "utf-8")
|
|
1303
1487
|
);
|
|
1304
1488
|
return packageJson.workspaces !== void 0;
|
|
1305
1489
|
} catch (error2) {
|
|
@@ -1308,104 +1492,6 @@ function isMonorepo({
|
|
|
1308
1492
|
}
|
|
1309
1493
|
}
|
|
1310
1494
|
|
|
1311
|
-
// src/config/microfrontends/utils/find-package-root.ts
|
|
1312
|
-
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
1313
|
-
var import_node_path4 = __toESM(require("path"), 1);
|
|
1314
|
-
var PACKAGE_JSON = "package.json";
|
|
1315
|
-
function findPackageRoot(startDir) {
|
|
1316
|
-
let currentDir = startDir || process.cwd();
|
|
1317
|
-
while (currentDir !== import_node_path4.default.parse(currentDir).root) {
|
|
1318
|
-
const pkgJsonPath = import_node_path4.default.join(currentDir, PACKAGE_JSON);
|
|
1319
|
-
if (import_node_fs4.default.existsSync(pkgJsonPath)) {
|
|
1320
|
-
return currentDir;
|
|
1321
|
-
}
|
|
1322
|
-
currentDir = import_node_path4.default.dirname(currentDir);
|
|
1323
|
-
}
|
|
1324
|
-
throw new Error(
|
|
1325
|
-
`The root of the package that contains the \`package.json\` file for the \`${startDir}\` directory could not be found.`
|
|
1326
|
-
);
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
// src/config/microfrontends/utils/find-config.ts
|
|
1330
|
-
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
1331
|
-
var import_node_path5 = require("path");
|
|
1332
|
-
function findConfig({
|
|
1333
|
-
dir,
|
|
1334
|
-
customConfigFilename
|
|
1335
|
-
}) {
|
|
1336
|
-
for (const filename of getPossibleConfigurationFilenames({
|
|
1337
|
-
customConfigFilename
|
|
1338
|
-
})) {
|
|
1339
|
-
const maybeConfig = (0, import_node_path5.join)(dir, filename);
|
|
1340
|
-
if (import_node_fs5.default.existsSync(maybeConfig)) {
|
|
1341
|
-
return maybeConfig;
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
1344
|
-
return null;
|
|
1345
|
-
}
|
|
1346
|
-
|
|
1347
|
-
// src/config/microfrontends/utils/get-application-context.ts
|
|
1348
|
-
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
1349
|
-
var import_node_path6 = __toESM(require("path"), 1);
|
|
1350
|
-
function getApplicationContext(opts) {
|
|
1351
|
-
if (opts?.appName) {
|
|
1352
|
-
logger.debug("[MFE Config] Application name from appName parameter:", opts.appName);
|
|
1353
|
-
return { name: opts.appName };
|
|
1354
|
-
}
|
|
1355
|
-
if (process.env.VERCEL_PROJECT_NAME) {
|
|
1356
|
-
logger.debug("[MFE Config] Application name from VERCEL_PROJECT_NAME:", process.env.VERCEL_PROJECT_NAME);
|
|
1357
|
-
return {
|
|
1358
|
-
name: process.env.VERCEL_PROJECT_NAME,
|
|
1359
|
-
projectName: process.env.VERCEL_PROJECT_NAME
|
|
1360
|
-
};
|
|
1361
|
-
}
|
|
1362
|
-
if (process.env.NX_TASK_TARGET_PROJECT) {
|
|
1363
|
-
logger.debug("[MFE Config] Application name from NX_TASK_TARGET_PROJECT:", process.env.NX_TASK_TARGET_PROJECT);
|
|
1364
|
-
return {
|
|
1365
|
-
name: process.env.NX_TASK_TARGET_PROJECT,
|
|
1366
|
-
packageJsonName: process.env.NX_TASK_TARGET_PROJECT
|
|
1367
|
-
};
|
|
1368
|
-
}
|
|
1369
|
-
try {
|
|
1370
|
-
const vercelProjectJsonPath = import_node_fs6.default.readFileSync(
|
|
1371
|
-
import_node_path6.default.join(opts?.packageRoot || ".", ".vercel", "project.json"),
|
|
1372
|
-
"utf-8"
|
|
1373
|
-
);
|
|
1374
|
-
const projectJson = JSON.parse(vercelProjectJsonPath);
|
|
1375
|
-
if (projectJson.projectName) {
|
|
1376
|
-
logger.debug("[MFE Config] Application name from .vercel/project.json:", projectJson.projectName);
|
|
1377
|
-
return {
|
|
1378
|
-
name: projectJson.projectName,
|
|
1379
|
-
projectName: projectJson.projectName
|
|
1380
|
-
};
|
|
1381
|
-
}
|
|
1382
|
-
} catch (_) {
|
|
1383
|
-
}
|
|
1384
|
-
try {
|
|
1385
|
-
const packageJsonString = import_node_fs6.default.readFileSync(
|
|
1386
|
-
import_node_path6.default.join(opts?.packageRoot || ".", "package.json"),
|
|
1387
|
-
"utf-8"
|
|
1388
|
-
);
|
|
1389
|
-
const packageJson = JSON.parse(packageJsonString);
|
|
1390
|
-
if (!packageJson.name) {
|
|
1391
|
-
throw new MicrofrontendError(
|
|
1392
|
-
`package.json file missing required field "name"`,
|
|
1393
|
-
{
|
|
1394
|
-
type: "packageJson",
|
|
1395
|
-
subtype: "missing_field_name",
|
|
1396
|
-
source: "@vercel/microfrontends/next"
|
|
1397
|
-
}
|
|
1398
|
-
);
|
|
1399
|
-
}
|
|
1400
|
-
logger.debug("[MFE Config] Application name from package.json:", packageJson.name);
|
|
1401
|
-
return { name: packageJson.name, packageJsonName: packageJson.name };
|
|
1402
|
-
} catch (err) {
|
|
1403
|
-
throw MicrofrontendError.handle(err, {
|
|
1404
|
-
fileName: "package.json"
|
|
1405
|
-
});
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
1495
|
// src/config/microfrontends/server/utils/get-output-file-path.ts
|
|
1410
1496
|
var import_node_path7 = __toESM(require("path"), 1);
|
|
1411
1497
|
|
|
@@ -1419,8 +1505,8 @@ function getOutputFilePath() {
|
|
|
1419
1505
|
}
|
|
1420
1506
|
|
|
1421
1507
|
// src/config/microfrontends/server/validation.ts
|
|
1422
|
-
var import_jsonc_parser3 = require("jsonc-parser");
|
|
1423
1508
|
var import_ajv = require("ajv");
|
|
1509
|
+
var import_jsonc_parser3 = require("jsonc-parser");
|
|
1424
1510
|
|
|
1425
1511
|
// schema/schema.json
|
|
1426
1512
|
var schema_default = {
|
|
@@ -1448,9 +1534,7 @@ var schema_default = {
|
|
|
1448
1534
|
description: "Optional configuration options for the microfrontend."
|
|
1449
1535
|
}
|
|
1450
1536
|
},
|
|
1451
|
-
required: [
|
|
1452
|
-
"applications"
|
|
1453
|
-
],
|
|
1537
|
+
required: ["applications"],
|
|
1454
1538
|
additionalProperties: false,
|
|
1455
1539
|
description: "The microfrontends configuration schema. See https://vercel.com/docs/microfrontends/configuration."
|
|
1456
1540
|
},
|
|
@@ -1487,19 +1571,14 @@ var schema_default = {
|
|
|
1487
1571
|
description: "Development configuration for the default application."
|
|
1488
1572
|
}
|
|
1489
1573
|
},
|
|
1490
|
-
required: [
|
|
1491
|
-
"development"
|
|
1492
|
-
],
|
|
1574
|
+
required: ["development"],
|
|
1493
1575
|
additionalProperties: false
|
|
1494
1576
|
},
|
|
1495
1577
|
DefaultDevelopment: {
|
|
1496
1578
|
type: "object",
|
|
1497
1579
|
properties: {
|
|
1498
1580
|
local: {
|
|
1499
|
-
type: [
|
|
1500
|
-
"number",
|
|
1501
|
-
"string"
|
|
1502
|
-
],
|
|
1581
|
+
type: ["number", "string"],
|
|
1503
1582
|
description: "A local port number or host that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional).\n\nExamples of valid values: 8080, my.localhost.me, my.localhost.me:8080, https://my.localhost.me, https://my.localhost.me:8080.\n\nThe default value is http://localhost:<port> where port is a stable, unique port number (based on the application name).\n\nSee https://vercel.com/docs/microfrontends/local-development."
|
|
1504
1583
|
},
|
|
1505
1584
|
task: {
|
|
@@ -1511,9 +1590,7 @@ var schema_default = {
|
|
|
1511
1590
|
description: "Fallback for local development, could point to any environment. This is required for the default app. This value is used as the fallback for child apps as well if they do not have a fallback.\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\nSee https://vercel.com/docs/microfrontends/local-development."
|
|
1512
1591
|
}
|
|
1513
1592
|
},
|
|
1514
|
-
required: [
|
|
1515
|
-
"fallback"
|
|
1516
|
-
],
|
|
1593
|
+
required: ["fallback"],
|
|
1517
1594
|
additionalProperties: false
|
|
1518
1595
|
},
|
|
1519
1596
|
ChildApplication: {
|
|
@@ -1536,19 +1613,14 @@ var schema_default = {
|
|
|
1536
1613
|
description: "The name of the asset prefix to use instead of the auto-generated name.\n\nThe asset prefix is used to prefix all paths to static assets, such as JS, CSS, or images that are served by a specific application. It is necessary to ensure there are no conflicts with other applications on the same domain.\n\nAn auto-generated asset prefix of the form `vc-ap-<hash>` is used when this field is not provided.\n\nWhen this field is provided, `/${assetPrefix}/:path*` must also be added to the list of paths in the `routing` field. Changing the asset prefix after a microfrontend application has already been deployed is not a forwards and backwards compatible change, and the asset prefix should be added to the `routing` field and deployed before setting the `assetPrefix` field.\n\nThe default value is the auto-generated asset prefix of the form `vc-ap-<hash>`.\n\nSee https://vercel.com/docs/microfrontends/path-routing#asset-prefix."
|
|
1537
1614
|
}
|
|
1538
1615
|
},
|
|
1539
|
-
required: [
|
|
1540
|
-
"routing"
|
|
1541
|
-
],
|
|
1616
|
+
required: ["routing"],
|
|
1542
1617
|
additionalProperties: false
|
|
1543
1618
|
},
|
|
1544
1619
|
ChildDevelopment: {
|
|
1545
1620
|
type: "object",
|
|
1546
1621
|
properties: {
|
|
1547
1622
|
local: {
|
|
1548
|
-
type: [
|
|
1549
|
-
"number",
|
|
1550
|
-
"string"
|
|
1551
|
-
],
|
|
1623
|
+
type: ["number", "string"],
|
|
1552
1624
|
description: "A local port number or host that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional).\n\nExamples of valid values: 8080, my.localhost.me, my.localhost.me:8080, https://my.localhost.me, https://my.localhost.me:8080.\n\nThe default value is http://localhost:<port> where port is a stable, unique port number (based on the application name).\n\nSee https://vercel.com/docs/microfrontends/local-development."
|
|
1553
1625
|
},
|
|
1554
1626
|
task: {
|
|
@@ -1588,9 +1660,7 @@ var schema_default = {
|
|
|
1588
1660
|
description: "A list of path expressions that are routed to this application. See https://vercel.com/docs/microfrontends/path-routing#supported-path-expressions."
|
|
1589
1661
|
}
|
|
1590
1662
|
},
|
|
1591
|
-
required: [
|
|
1592
|
-
"paths"
|
|
1593
|
-
],
|
|
1663
|
+
required: ["paths"],
|
|
1594
1664
|
additionalProperties: false,
|
|
1595
1665
|
description: "A group of paths that is routed to this application."
|
|
1596
1666
|
},
|
|
@@ -2663,6 +2733,11 @@ var LocalProxy = class {
|
|
|
2663
2733
|
`The following apps passed via --local-apps are not in the microfrontends config: ${unknownApps.join(", ")} (microfrontends config contains: ${Array.from(allApps).join(", ")})`
|
|
2664
2734
|
);
|
|
2665
2735
|
}
|
|
2736
|
+
if (process.env[MFE_APP_PORT_ENV] && localApps.length > 1) {
|
|
2737
|
+
throw new Error(
|
|
2738
|
+
`${MFE_APP_PORT_ENV} cannot be used when multiple applications are running locally. You have ${localApps.length} local apps: ${localApps.join(", ")}. Either run a single app locally or remove the ${MFE_APP_PORT_ENV} environment variable.`
|
|
2739
|
+
);
|
|
2740
|
+
}
|
|
2666
2741
|
}
|
|
2667
2742
|
startServer() {
|
|
2668
2743
|
const httpServer = http.createServer(
|
|
@@ -2934,10 +3009,23 @@ function formatProxyTarget(target) {
|
|
|
2934
3009
|
var import_node_process = require("process");
|
|
2935
3010
|
|
|
2936
3011
|
// src/utils/mfe-port.ts
|
|
2937
|
-
var import_node_path9 = __toESM(require("path"), 1);
|
|
2938
3012
|
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
3013
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
3014
|
+
var MFE_APP_PORT_ENV2 = "MFE_APP_PORT";
|
|
2939
3015
|
function mfePort(packageDir) {
|
|
2940
3016
|
const { name: appName, version } = getPackageJson(packageDir);
|
|
3017
|
+
const portOverride = process.env[MFE_APP_PORT_ENV2];
|
|
3018
|
+
if (portOverride) {
|
|
3019
|
+
const port = Number.parseInt(portOverride, 10);
|
|
3020
|
+
if (!Number.isNaN(port) && port > 0 && port < 65536) {
|
|
3021
|
+
return {
|
|
3022
|
+
name: appName,
|
|
3023
|
+
version,
|
|
3024
|
+
port,
|
|
3025
|
+
overridden: true
|
|
3026
|
+
};
|
|
3027
|
+
}
|
|
3028
|
+
}
|
|
2941
3029
|
try {
|
|
2942
3030
|
const result = loadConfig({ packageDir, appName });
|
|
2943
3031
|
const { port } = result;
|
|
@@ -2975,10 +3063,11 @@ function displayPort() {
|
|
|
2975
3063
|
header(portInfo);
|
|
2976
3064
|
logger.info(portInfo.port);
|
|
2977
3065
|
}
|
|
2978
|
-
function header({ name, version, port }) {
|
|
3066
|
+
function header({ name, version, port, overridden }) {
|
|
3067
|
+
const portSource = overridden ? `${port} (override via ${MFE_APP_PORT_ENV2})` : port;
|
|
2979
3068
|
logger.error(`
|
|
2980
3069
|
\u25B2 ${name}@${version}
|
|
2981
|
-
\xB7 setting port to ${
|
|
3070
|
+
\xB7 setting port to ${portSource}
|
|
2982
3071
|
`);
|
|
2983
3072
|
}
|
|
2984
3073
|
|