@vercel/microfrontends 0.10.1 → 0.11.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.
- package/dist/bin/cli.cjs +261 -91
- package/dist/{index-acb44057.d.ts → index-a99d5459.d.ts} +2 -2
- package/dist/next/config.cjs +10 -1
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.js +10 -1
- package/dist/next/config.js.map +1 -1
- package/dist/next/middleware.cjs +17 -1
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.js +17 -1
- package/dist/next/middleware.js.map +1 -1
- package/dist/{types-7b1cd9f7.d.ts → types-0030abae.d.ts} +0 -1
- package/dist/{types-c3d15d04.d.ts → types-c777c2f5.d.ts} +1 -1
- package/dist/v2/config.cjs +1 -1
- package/dist/v2/config.cjs.map +1 -1
- package/dist/v2/config.d.ts +3 -3
- package/dist/v2/config.js +1 -1
- package/dist/v2/config.js.map +1 -1
- package/dist/v2/microfrontends/server.cjs +214 -44
- package/dist/v2/microfrontends/server.cjs.map +1 -1
- package/dist/v2/microfrontends/server.d.ts +22 -3
- package/dist/v2/microfrontends/server.js +214 -44
- package/dist/v2/microfrontends/server.js.map +1 -1
- package/dist/v2/microfrontends.cjs +1 -1
- package/dist/v2/microfrontends.cjs.map +1 -1
- package/dist/v2/microfrontends.d.ts +3 -3
- package/dist/v2/microfrontends.js +1 -1
- package/dist/v2/microfrontends.js.map +1 -1
- package/dist/v2/next/config.cjs +248 -73
- package/dist/v2/next/config.cjs.map +1 -1
- package/dist/v2/next/config.js +248 -73
- package/dist/v2/next/config.js.map +1 -1
- package/dist/v2/next/endpoints.cjs +5 -2
- package/dist/v2/next/endpoints.cjs.map +1 -1
- package/dist/v2/next/endpoints.d.ts +1 -1
- package/dist/v2/next/endpoints.js +5 -2
- package/dist/v2/next/endpoints.js.map +1 -1
- package/dist/v2/next/middleware.cjs +107 -87
- package/dist/v2/next/middleware.cjs.map +1 -1
- package/dist/v2/next/middleware.js +107 -87
- package/dist/v2/next/middleware.js.map +1 -1
- package/dist/v2/overrides.cjs +1 -1
- package/dist/v2/overrides.cjs.map +1 -1
- package/dist/v2/overrides.d.ts +3 -3
- package/dist/v2/overrides.js +1 -1
- package/dist/v2/overrides.js.map +1 -1
- package/dist/v2/schema.d.ts +1 -1
- package/dist/validation.cjs +0 -3
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.d.ts +0 -1
- package/dist/validation.js +0 -3
- package/dist/validation.js.map +1 -1
- package/package.json +7 -7
- package/schema/schema-v2.json +0 -3
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/config-v2/microfrontends/server/index.ts
|
|
2
|
-
import
|
|
3
|
-
import { dirname as
|
|
2
|
+
import fs4 from "node:fs";
|
|
3
|
+
import { dirname as dirname3, join } from "node:path";
|
|
4
4
|
|
|
5
5
|
// src/config-v2/overrides/constants.ts
|
|
6
|
-
var OVERRIDES_COOKIE_PREFIX = "vercel-
|
|
6
|
+
var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
|
|
7
7
|
var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
8
8
|
|
|
9
9
|
// src/config-v2/overrides/is-override-cookie.ts
|
|
@@ -184,21 +184,21 @@ var MicrofrontendConfigClient = class {
|
|
|
184
184
|
isEqual(other) {
|
|
185
185
|
return JSON.stringify(this.applications) === JSON.stringify(other.applications);
|
|
186
186
|
}
|
|
187
|
-
getApplicationNameForPath(
|
|
188
|
-
if (!
|
|
187
|
+
getApplicationNameForPath(path5) {
|
|
188
|
+
if (!path5.startsWith("/")) {
|
|
189
189
|
throw new Error(`Path must start with a /`);
|
|
190
190
|
}
|
|
191
|
-
if (this.pathCache[
|
|
192
|
-
return this.pathCache[
|
|
191
|
+
if (this.pathCache[path5]) {
|
|
192
|
+
return this.pathCache[path5];
|
|
193
193
|
}
|
|
194
|
-
const pathname = new URL(
|
|
194
|
+
const pathname = new URL(path5, "https://example.com").pathname;
|
|
195
195
|
for (const [name, application] of Object.entries(this.applications)) {
|
|
196
196
|
if (application.routing) {
|
|
197
197
|
for (const group of application.routing) {
|
|
198
198
|
for (const childPath of group.paths) {
|
|
199
199
|
const regexp = pathToRegexp(childPath);
|
|
200
200
|
if (regexp.test(pathname)) {
|
|
201
|
-
this.pathCache[
|
|
201
|
+
this.pathCache[path5] = name;
|
|
202
202
|
return name;
|
|
203
203
|
}
|
|
204
204
|
}
|
|
@@ -211,7 +211,7 @@ var MicrofrontendConfigClient = class {
|
|
|
211
211
|
if (!defaultApplication) {
|
|
212
212
|
return null;
|
|
213
213
|
}
|
|
214
|
-
this.pathCache[
|
|
214
|
+
this.pathCache[path5] = defaultApplication[0];
|
|
215
215
|
return defaultApplication[0];
|
|
216
216
|
}
|
|
217
217
|
serialize() {
|
|
@@ -243,22 +243,22 @@ var validateConfigPaths = (applicationConfigsById) => {
|
|
|
243
243
|
continue;
|
|
244
244
|
}
|
|
245
245
|
for (const pathMatch of app.routing) {
|
|
246
|
-
for (const
|
|
247
|
-
const tokens = parsePathRegexp(
|
|
246
|
+
for (const path5 of pathMatch.paths) {
|
|
247
|
+
const tokens = parsePathRegexp(path5);
|
|
248
248
|
for (const token of tokens.slice(0, -1)) {
|
|
249
249
|
if (typeof token !== "string") {
|
|
250
250
|
errors.push(
|
|
251
|
-
`Path ${
|
|
251
|
+
`Path ${path5} may only have a :wildcard in the last path component`
|
|
252
252
|
);
|
|
253
253
|
}
|
|
254
254
|
}
|
|
255
|
-
const existing = pathsByApplicationId.get(
|
|
255
|
+
const existing = pathsByApplicationId.get(path5);
|
|
256
256
|
if (existing) {
|
|
257
257
|
existing.applications.push(id);
|
|
258
258
|
} else {
|
|
259
|
-
pathsByApplicationId.set(
|
|
259
|
+
pathsByApplicationId.set(path5, {
|
|
260
260
|
applications: [id],
|
|
261
|
-
matcher: pathToRegexp2(
|
|
261
|
+
matcher: pathToRegexp2(path5),
|
|
262
262
|
applicationId: id
|
|
263
263
|
});
|
|
264
264
|
}
|
|
@@ -266,10 +266,10 @@ var validateConfigPaths = (applicationConfigsById) => {
|
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
268
|
const entries = Array.from(pathsByApplicationId.entries());
|
|
269
|
-
entries.forEach(([
|
|
269
|
+
entries.forEach(([path5, { applications: ids, matcher, applicationId }]) => {
|
|
270
270
|
if (ids.length > 1) {
|
|
271
271
|
errors.push(
|
|
272
|
-
`Duplicate path "${
|
|
272
|
+
`Duplicate path "${path5}" for applications "${ids.join(", ")}"`
|
|
273
273
|
);
|
|
274
274
|
}
|
|
275
275
|
entries.forEach(
|
|
@@ -277,14 +277,14 @@ var validateConfigPaths = (applicationConfigsById) => {
|
|
|
277
277
|
matchPath,
|
|
278
278
|
{ applications: matchIds, applicationId: matchApplicationId }
|
|
279
279
|
]) => {
|
|
280
|
-
if (
|
|
280
|
+
if (path5 === matchPath) {
|
|
281
281
|
return;
|
|
282
282
|
}
|
|
283
283
|
if (applicationId === matchApplicationId) {
|
|
284
284
|
return;
|
|
285
285
|
}
|
|
286
286
|
if (matcher.test(matchPath)) {
|
|
287
|
-
const source = `"${
|
|
287
|
+
const source = `"${path5}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
288
288
|
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
289
289
|
errors.push(
|
|
290
290
|
`Overlapping path detected between ${source} and ${destination}`
|
|
@@ -849,8 +849,115 @@ function findPackagePath(opts) {
|
|
|
849
849
|
return result;
|
|
850
850
|
}
|
|
851
851
|
|
|
852
|
-
// src/config-v2/microfrontends/
|
|
852
|
+
// src/config-v2/microfrontends/utils/find-default-package.ts
|
|
853
|
+
import { dirname as dirname2 } from "node:path";
|
|
854
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
855
|
+
import fg2 from "fast-glob";
|
|
856
|
+
var configCache2 = {};
|
|
857
|
+
function findDefaultMicrofrontendsPackages({
|
|
858
|
+
repositoryRoot,
|
|
859
|
+
applicationName
|
|
860
|
+
}) {
|
|
861
|
+
try {
|
|
862
|
+
const microfrontendsJsonPaths = fg2.globSync("**/microfrontends.json", {
|
|
863
|
+
cwd: repositoryRoot,
|
|
864
|
+
absolute: true,
|
|
865
|
+
onlyFiles: true,
|
|
866
|
+
followSymbolicLinks: false,
|
|
867
|
+
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
868
|
+
});
|
|
869
|
+
const matchingPaths = [];
|
|
870
|
+
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
871
|
+
const microfrontendsJsonContent = readFileSync2(
|
|
872
|
+
microfrontendsJsonPath,
|
|
873
|
+
"utf-8"
|
|
874
|
+
);
|
|
875
|
+
const microfrontendsJson = JSON.parse(
|
|
876
|
+
microfrontendsJsonContent
|
|
877
|
+
);
|
|
878
|
+
if (isMainConfig(microfrontendsJson) && microfrontendsJson.applications[applicationName]) {
|
|
879
|
+
matchingPaths.push(microfrontendsJsonPath);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
if (matchingPaths.length > 1) {
|
|
883
|
+
throw new Error(
|
|
884
|
+
`Found multiple default applications referencing "${applicationName}" in the repository, this is not yet supported.
|
|
885
|
+
${matchingPaths.join("\n \u2022 ")}`
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
if (matchingPaths.length === 0) {
|
|
889
|
+
throw new Error(
|
|
890
|
+
`Could not find default application with "applications.${applicationName}"`
|
|
891
|
+
);
|
|
892
|
+
}
|
|
893
|
+
const [packageJsonPath] = matchingPaths;
|
|
894
|
+
return dirname2(packageJsonPath);
|
|
895
|
+
} catch (error) {
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
function findDefaultMicrofrontendsPackage(opts) {
|
|
900
|
+
const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;
|
|
901
|
+
if (configCache2[cacheKey]) {
|
|
902
|
+
return configCache2[cacheKey];
|
|
903
|
+
}
|
|
904
|
+
const result = findDefaultMicrofrontendsPackages(opts);
|
|
905
|
+
if (!result) {
|
|
906
|
+
throw new Error(
|
|
907
|
+
`Error trying to resolve the main microfrontends.json configuration`
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
configCache2[cacheKey] = result;
|
|
911
|
+
return result;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
// src/config-v2/microfrontends/utils/is-monorepo.ts
|
|
915
|
+
import fs2 from "node:fs";
|
|
853
916
|
import path2 from "node:path";
|
|
917
|
+
function isMonorepo({
|
|
918
|
+
repositoryRoot
|
|
919
|
+
}) {
|
|
920
|
+
try {
|
|
921
|
+
if (fs2.existsSync(path2.join(repositoryRoot, "pnpm-workspace.yaml"))) {
|
|
922
|
+
return true;
|
|
923
|
+
}
|
|
924
|
+
if (fs2.existsSync(path2.join(repositoryRoot, "vlt-workspaces.json"))) {
|
|
925
|
+
return true;
|
|
926
|
+
}
|
|
927
|
+
const packageJsonPath = path2.join(repositoryRoot, "package.json");
|
|
928
|
+
if (!fs2.existsSync(packageJsonPath)) {
|
|
929
|
+
return false;
|
|
930
|
+
}
|
|
931
|
+
const packageJson = JSON.parse(
|
|
932
|
+
fs2.readFileSync(packageJsonPath, "utf-8")
|
|
933
|
+
);
|
|
934
|
+
return packageJson.workspaces !== void 0;
|
|
935
|
+
} catch (error) {
|
|
936
|
+
console.error("Error determining if repository is a monorepo", error);
|
|
937
|
+
return false;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// src/config-v2/microfrontends/utils/find-package-root.ts
|
|
942
|
+
import fs3 from "node:fs";
|
|
943
|
+
import path3 from "node:path";
|
|
944
|
+
var PACKAGE_JSON = "package.json";
|
|
945
|
+
function findPackageRoot(startDir) {
|
|
946
|
+
let currentDir = startDir || process.cwd();
|
|
947
|
+
while (currentDir !== path3.parse(currentDir).root) {
|
|
948
|
+
const pkgJsonPath = path3.join(currentDir, PACKAGE_JSON);
|
|
949
|
+
if (fs3.existsSync(pkgJsonPath)) {
|
|
950
|
+
return currentDir;
|
|
951
|
+
}
|
|
952
|
+
currentDir = path3.dirname(currentDir);
|
|
953
|
+
}
|
|
954
|
+
throw new Error(
|
|
955
|
+
"Package root not found. Specify the root of the package with the `package.root` option."
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// src/config-v2/microfrontends/server/utils/get-output-file-path.ts
|
|
960
|
+
import path4 from "node:path";
|
|
854
961
|
|
|
855
962
|
// src/config-v2/microfrontends/server/constants.ts
|
|
856
963
|
var MFE_CONFIG_DEFAULT_FILE_PATH = "microfrontends";
|
|
@@ -864,13 +971,13 @@ function isVercel() {
|
|
|
864
971
|
// src/config-v2/microfrontends/server/utils/get-output-file-path.ts
|
|
865
972
|
function getOutputFilePath() {
|
|
866
973
|
if (isVercel()) {
|
|
867
|
-
return
|
|
974
|
+
return path4.join(
|
|
868
975
|
".vercel",
|
|
869
976
|
MFE_CONFIG_DEFAULT_FILE_PATH,
|
|
870
977
|
MFE_CONFIG_DEFAULT_FILE_NAME
|
|
871
978
|
);
|
|
872
979
|
}
|
|
873
|
-
return
|
|
980
|
+
return path4.join(MFE_CONFIG_DEFAULT_FILE_PATH, MFE_CONFIG_DEFAULT_FILE_NAME);
|
|
874
981
|
}
|
|
875
982
|
|
|
876
983
|
// src/config-v2/microfrontends/server/validation.ts
|
|
@@ -1084,9 +1191,6 @@ var schema_v2_default = {
|
|
|
1084
1191
|
projectId: {
|
|
1085
1192
|
type: "string",
|
|
1086
1193
|
description: "Vercel project ID"
|
|
1087
|
-
},
|
|
1088
|
-
routeSpeedInsightsToDefaultZone: {
|
|
1089
|
-
type: "boolean"
|
|
1090
1194
|
}
|
|
1091
1195
|
},
|
|
1092
1196
|
required: ["projectId"]
|
|
@@ -1256,8 +1360,8 @@ var MicrofrontendsServer = class extends Microfrontends {
|
|
|
1256
1360
|
pretty: true
|
|
1257
1361
|
}) {
|
|
1258
1362
|
const outputPath = getOutputFilePath();
|
|
1259
|
-
|
|
1260
|
-
|
|
1363
|
+
fs4.mkdirSync(dirname3(outputPath), { recursive: true });
|
|
1364
|
+
fs4.writeFileSync(
|
|
1261
1365
|
outputPath,
|
|
1262
1366
|
JSON.stringify(
|
|
1263
1367
|
this.config.toSchemaJson(),
|
|
@@ -1319,6 +1423,69 @@ var MicrofrontendsServer = class extends Microfrontends {
|
|
|
1319
1423
|
}
|
|
1320
1424
|
return config;
|
|
1321
1425
|
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Looks up the configuration by inferring the package root and looking for a microfrontends.json file. If a file is not found,
|
|
1428
|
+
* it will look for a package in the repository with a microfrontends.json file that contains the current application
|
|
1429
|
+
* and use that configuration.
|
|
1430
|
+
*
|
|
1431
|
+
* This can return either a Child or Main configuration.
|
|
1432
|
+
*/
|
|
1433
|
+
static infer({
|
|
1434
|
+
directory,
|
|
1435
|
+
filePath,
|
|
1436
|
+
meta,
|
|
1437
|
+
cookies,
|
|
1438
|
+
options
|
|
1439
|
+
} = {}) {
|
|
1440
|
+
if (filePath && meta) {
|
|
1441
|
+
return MicrofrontendsServer.fromFile({
|
|
1442
|
+
filePath,
|
|
1443
|
+
cookies,
|
|
1444
|
+
meta,
|
|
1445
|
+
options
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
try {
|
|
1449
|
+
const packageRoot = findPackageRoot(directory);
|
|
1450
|
+
const packageJsonPath = join(packageRoot, "package.json");
|
|
1451
|
+
const packageJson = JSON.parse(
|
|
1452
|
+
fs4.readFileSync(packageJsonPath, "utf-8")
|
|
1453
|
+
);
|
|
1454
|
+
if (!packageJson.name) {
|
|
1455
|
+
throw new Error(`No name found in package.json at ${packageJsonPath}`);
|
|
1456
|
+
}
|
|
1457
|
+
const configMeta = meta ?? { fromApp: packageJson.name };
|
|
1458
|
+
const maybeConfig = join(packageRoot, "microfrontends.json");
|
|
1459
|
+
if (fs4.existsSync(maybeConfig)) {
|
|
1460
|
+
return MicrofrontendsServer.fromFile({
|
|
1461
|
+
filePath: maybeConfig,
|
|
1462
|
+
cookies,
|
|
1463
|
+
meta: configMeta,
|
|
1464
|
+
options
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
const repositoryRoot = findRepositoryRoot();
|
|
1468
|
+
const isMonorepo2 = isMonorepo({ repositoryRoot });
|
|
1469
|
+
if (isMonorepo2) {
|
|
1470
|
+
const defaultPackage = findDefaultMicrofrontendsPackage({
|
|
1471
|
+
repositoryRoot,
|
|
1472
|
+
applicationName: packageJson.name
|
|
1473
|
+
});
|
|
1474
|
+
return MicrofrontendsServer.fromFile({
|
|
1475
|
+
filePath: join(defaultPackage, "microfrontends.json"),
|
|
1476
|
+
cookies,
|
|
1477
|
+
meta: configMeta,
|
|
1478
|
+
options
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
throw new Error("Unable to infer");
|
|
1482
|
+
} catch (e) {
|
|
1483
|
+
throw new MicrofrontendError(
|
|
1484
|
+
"Unable to infer microfrontends configuration",
|
|
1485
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1486
|
+
);
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1322
1489
|
/*
|
|
1323
1490
|
* Generates a MicrofrontendsServer instance from a file.
|
|
1324
1491
|
*/
|
|
@@ -1329,25 +1496,28 @@ var MicrofrontendsServer = class extends Microfrontends {
|
|
|
1329
1496
|
options
|
|
1330
1497
|
}) {
|
|
1331
1498
|
try {
|
|
1332
|
-
const configJson =
|
|
1499
|
+
const configJson = fs4.readFileSync(filePath, "utf-8");
|
|
1333
1500
|
const config = MicrofrontendsServer.validate(configJson);
|
|
1334
1501
|
if (!isMainConfig(config) && (options == null ? void 0 : options.resolveMainConfig)) {
|
|
1335
1502
|
const repositoryRoot = findRepositoryRoot();
|
|
1336
|
-
const
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1503
|
+
const isMonorepo2 = isMonorepo({ repositoryRoot });
|
|
1504
|
+
if (isMonorepo2) {
|
|
1505
|
+
const packagePath = findPackagePath({
|
|
1506
|
+
repositoryRoot,
|
|
1507
|
+
name: config.partOf
|
|
1508
|
+
});
|
|
1509
|
+
if (!packagePath) {
|
|
1510
|
+
throw new MicrofrontendError(
|
|
1511
|
+
`Could not find default application "${config.partOf}" in the repository`,
|
|
1512
|
+
{ type: "config", subtype: "not_found" }
|
|
1513
|
+
);
|
|
1514
|
+
}
|
|
1515
|
+
const mainConfigPath = join(packagePath, "microfrontends.json");
|
|
1516
|
+
return MicrofrontendsServer.fromMainConfigFile({
|
|
1517
|
+
filePath: mainConfigPath,
|
|
1518
|
+
overrides: cookies ? parseOverrides(cookies) : void 0
|
|
1519
|
+
});
|
|
1345
1520
|
}
|
|
1346
|
-
const mainConfigPath = join(packagePath, "microfrontends.json");
|
|
1347
|
-
return MicrofrontendsServer.fromMainConfigFile({
|
|
1348
|
-
filePath: mainConfigPath,
|
|
1349
|
-
overrides: cookies ? parseOverrides(cookies) : void 0
|
|
1350
|
-
});
|
|
1351
1521
|
}
|
|
1352
1522
|
return new MicrofrontendsServer({
|
|
1353
1523
|
config,
|
|
@@ -1368,7 +1538,7 @@ var MicrofrontendsServer = class extends Microfrontends {
|
|
|
1368
1538
|
overrides
|
|
1369
1539
|
}) {
|
|
1370
1540
|
try {
|
|
1371
|
-
const config =
|
|
1541
|
+
const config = fs4.readFileSync(filePath, "utf-8");
|
|
1372
1542
|
const validatedConfig = MicrofrontendsServer.validate(config);
|
|
1373
1543
|
if (!isMainConfig(validatedConfig)) {
|
|
1374
1544
|
throw new MicrofrontendError(
|