@vercel/microfrontends 0.14.0 → 0.16.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 +392 -1620
- package/dist/config.cjs +478 -1001
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.ts +4 -25
- package/dist/config.js +474 -980
- package/dist/config.js.map +1 -1
- package/dist/{v2/microfrontends → microfrontends}/server.cjs +91 -150
- package/dist/microfrontends/server.cjs.map +1 -0
- package/dist/{v2/microfrontends → microfrontends}/server.d.ts +4 -4
- package/dist/{v2/microfrontends → microfrontends}/server.js +91 -150
- package/dist/microfrontends/server.js.map +1 -0
- package/dist/{v2/microfrontends.cjs → microfrontends.cjs} +49 -28
- package/dist/microfrontends.cjs.map +1 -0
- package/dist/{v2/microfrontends.d.ts → microfrontends.d.ts} +4 -4
- package/dist/{v2/microfrontends.js → microfrontends.js} +48 -27
- package/dist/microfrontends.js.map +1 -0
- package/dist/next/client.cjs +1 -1
- package/dist/next/client.cjs.map +1 -1
- package/dist/next/client.js +1 -1
- package/dist/next/client.js.map +1 -1
- package/dist/next/config.cjs +1344 -1024
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.d.ts +1 -1
- package/dist/next/config.js +1343 -1023
- package/dist/next/config.js.map +1 -1
- package/dist/next/endpoints.cjs +77 -18
- package/dist/next/endpoints.cjs.map +1 -1
- package/dist/next/endpoints.d.ts +13 -2
- package/dist/next/endpoints.js +77 -18
- package/dist/next/endpoints.js.map +1 -1
- package/dist/next/middleware.cjs +765 -395
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.d.ts +10 -5
- package/dist/next/middleware.js +765 -395
- package/dist/next/middleware.js.map +1 -1
- package/dist/next/testing.cjs +615 -1031
- package/dist/next/testing.cjs.map +1 -1
- package/dist/next/testing.d.ts +14 -12
- package/dist/next/testing.js +609 -1015
- package/dist/next/testing.js.map +1 -1
- package/dist/overrides.cjs +40 -108
- package/dist/overrides.cjs.map +1 -1
- package/dist/overrides.d.ts +24 -2
- package/dist/overrides.js +36 -106
- package/dist/overrides.js.map +1 -1
- package/dist/{v2/routing.cjs → routing.cjs} +3 -3
- package/dist/routing.cjs.map +1 -0
- package/dist/{v2/schema.cjs → schema.cjs} +1 -1
- package/dist/schema.cjs.map +1 -0
- package/dist/schema.d.ts +1 -0
- package/dist/utils/mfe-port.cjs +237 -1338
- package/dist/utils/mfe-port.cjs.map +1 -1
- package/dist/utils/mfe-port.js +230 -1331
- package/dist/utils/mfe-port.js.map +1 -1
- package/dist/validation.cjs +31 -361
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.d.ts +3 -146
- package/dist/validation.js +30 -359
- package/dist/validation.js.map +1 -1
- package/package.json +29 -92
- package/schema/schema.json +174 -244
- package/dist/config/client.cjs +0 -54
- package/dist/config/client.cjs.map +0 -1
- package/dist/config/client.d.ts +0 -23
- package/dist/config/client.js +0 -28
- package/dist/config/client.js.map +0 -1
- package/dist/config/edge.cjs +0 -508
- package/dist/config/edge.cjs.map +0 -1
- package/dist/config/edge.d.ts +0 -20
- package/dist/config/edge.js +0 -481
- package/dist/config/edge.js.map +0 -1
- package/dist/microfrontend-config-983a5139.d.ts +0 -154
- package/dist/schema-2922d49e.d.ts +0 -182
- package/dist/v2/config.cjs +0 -709
- package/dist/v2/config.cjs.map +0 -1
- package/dist/v2/config.d.ts +0 -4
- package/dist/v2/config.js +0 -684
- package/dist/v2/config.js.map +0 -1
- package/dist/v2/microfrontends/server.cjs.map +0 -1
- package/dist/v2/microfrontends/server.js.map +0 -1
- package/dist/v2/microfrontends.cjs.map +0 -1
- package/dist/v2/microfrontends.js.map +0 -1
- package/dist/v2/next/client.cjs +0 -3
- package/dist/v2/next/client.cjs.map +0 -1
- package/dist/v2/next/client.d.ts +0 -45
- package/dist/v2/next/client.js +0 -3
- package/dist/v2/next/client.js.map +0 -1
- package/dist/v2/next/config.cjs +0 -2178
- package/dist/v2/next/config.cjs.map +0 -1
- package/dist/v2/next/config.d.ts +0 -22
- package/dist/v2/next/config.js +0 -2143
- package/dist/v2/next/config.js.map +0 -1
- package/dist/v2/next/endpoints.cjs +0 -141
- package/dist/v2/next/endpoints.cjs.map +0 -1
- package/dist/v2/next/endpoints.d.ts +0 -26
- package/dist/v2/next/endpoints.js +0 -116
- package/dist/v2/next/endpoints.js.map +0 -1
- package/dist/v2/next/middleware.cjs +0 -1099
- package/dist/v2/next/middleware.cjs.map +0 -1
- package/dist/v2/next/middleware.d.ts +0 -34
- package/dist/v2/next/middleware.js +0 -1071
- package/dist/v2/next/middleware.js.map +0 -1
- package/dist/v2/next/testing.cjs +0 -992
- package/dist/v2/next/testing.cjs.map +0 -1
- package/dist/v2/next/testing.d.ts +0 -55
- package/dist/v2/next/testing.js +0 -961
- package/dist/v2/next/testing.js.map +0 -1
- package/dist/v2/overrides.cjs +0 -75
- package/dist/v2/overrides.cjs.map +0 -1
- package/dist/v2/overrides.d.ts +0 -24
- package/dist/v2/overrides.js +0 -45
- package/dist/v2/overrides.js.map +0 -1
- package/dist/v2/routing.cjs.map +0 -1
- package/dist/v2/schema.cjs.map +0 -1
- package/dist/v2/schema.d.ts +0 -1
- package/schema/schema-v2.json +0 -266
- /package/dist/{v2/routing.d.ts → routing.d.ts} +0 -0
- /package/dist/{v2/routing.js → routing.js} +0 -0
- /package/dist/{v2/routing.js.map → routing.js.map} +0 -0
- /package/dist/{v2/schema.js → schema.js} +0 -0
- /package/dist/{v2/schema.js.map → schema.js.map} +0 -0
package/dist/next/config.cjs
CHANGED
|
@@ -33,33 +33,44 @@ __export(config_exports, {
|
|
|
33
33
|
withMicrofrontends: () => withMicrofrontends
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(config_exports);
|
|
36
|
-
var
|
|
36
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
37
37
|
|
|
38
|
-
// src/config/
|
|
39
|
-
var
|
|
38
|
+
// src/config/microfrontends/server/index.ts
|
|
39
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
40
|
+
var import_node_path8 = require("path");
|
|
40
41
|
|
|
41
|
-
// src/config
|
|
42
|
-
var
|
|
42
|
+
// src/config/overrides/constants.ts
|
|
43
|
+
var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
|
|
44
|
+
var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
43
45
|
|
|
44
|
-
// src/config
|
|
45
|
-
|
|
46
|
-
var
|
|
46
|
+
// src/config/overrides/is-override-cookie.ts
|
|
47
|
+
function isOverrideCookie(cookie) {
|
|
48
|
+
var _a;
|
|
49
|
+
return Boolean((_a = cookie.name) == null ? void 0 : _a.startsWith(OVERRIDES_COOKIE_PREFIX));
|
|
50
|
+
}
|
|
47
51
|
|
|
48
|
-
// src/
|
|
49
|
-
function
|
|
50
|
-
|
|
52
|
+
// src/config/overrides/get-override-from-cookie.ts
|
|
53
|
+
function getOverrideFromCookie(cookie) {
|
|
54
|
+
if (!isOverrideCookie(cookie) || !cookie.value)
|
|
55
|
+
return;
|
|
56
|
+
return {
|
|
57
|
+
application: cookie.name.replace(OVERRIDES_ENV_COOKIE_PREFIX, ""),
|
|
58
|
+
host: cookie.value
|
|
59
|
+
};
|
|
51
60
|
}
|
|
52
61
|
|
|
53
|
-
// src/config
|
|
54
|
-
function
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
// src/config/overrides/parse-overrides.ts
|
|
63
|
+
function parseOverrides(cookies) {
|
|
64
|
+
const overridesConfig = { applications: {} };
|
|
65
|
+
cookies.forEach((cookie) => {
|
|
66
|
+
const override = getOverrideFromCookie(cookie);
|
|
67
|
+
if (!override)
|
|
68
|
+
return;
|
|
69
|
+
overridesConfig.applications[override.application] = {
|
|
70
|
+
environment: { host: override.host }
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
return overridesConfig;
|
|
63
74
|
}
|
|
64
75
|
|
|
65
76
|
// src/config/errors.ts
|
|
@@ -154,131 +165,289 @@ var MicrofrontendError = class extends Error {
|
|
|
154
165
|
}
|
|
155
166
|
};
|
|
156
167
|
|
|
157
|
-
// src/
|
|
158
|
-
function
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
168
|
+
// src/config/microfrontends-config/utils/get-config-from-env.ts
|
|
169
|
+
function getConfigStringFromEnv() {
|
|
170
|
+
const config = process.env.MFE_CONFIG;
|
|
171
|
+
if (!config) {
|
|
172
|
+
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
173
|
+
type: "config",
|
|
174
|
+
subtype: "not_found_in_env"
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return config;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/config/microfrontends-config/isomorphic/index.ts
|
|
181
|
+
var import_jsonc_parser = require("jsonc-parser");
|
|
182
|
+
|
|
183
|
+
// src/config/schema/utils/is-main-config.ts
|
|
184
|
+
function isMainConfig(c) {
|
|
185
|
+
return !("partOf" in c);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/config/schema/utils/is-default-app.ts
|
|
189
|
+
function isDefaultApp(a) {
|
|
190
|
+
return !("routing" in a);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// src/config/microfrontends-config/client/index.ts
|
|
194
|
+
var import_path_to_regexp = require("path-to-regexp");
|
|
195
|
+
var MicrofrontendConfigClient = class {
|
|
196
|
+
constructor(config, opts) {
|
|
197
|
+
this.pathCache = {};
|
|
198
|
+
this.serialized = config;
|
|
199
|
+
if (opts == null ? void 0 : opts.removeFlaggedPaths) {
|
|
200
|
+
for (const app of Object.values(config.applications)) {
|
|
201
|
+
if (app.routing) {
|
|
202
|
+
app.routing = app.routing.filter((match) => !match.flag);
|
|
203
|
+
}
|
|
173
204
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
205
|
+
}
|
|
206
|
+
this.applications = config.applications;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Create a new `MicrofrontendConfigClient` from a JSON string.
|
|
210
|
+
* Config must be passed in to remain framework agnostic
|
|
211
|
+
*/
|
|
212
|
+
static fromEnv(config, opts) {
|
|
213
|
+
if (!config) {
|
|
214
|
+
throw new Error("No microfrontends configuration found");
|
|
215
|
+
}
|
|
216
|
+
return new MicrofrontendConfigClient(
|
|
217
|
+
JSON.parse(config),
|
|
218
|
+
opts
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
isEqual(other) {
|
|
222
|
+
return JSON.stringify(this.applications) === JSON.stringify(other.applications);
|
|
223
|
+
}
|
|
224
|
+
getApplicationNameForPath(path5) {
|
|
225
|
+
if (!path5.startsWith("/")) {
|
|
226
|
+
throw new Error(`Path must start with a /`);
|
|
227
|
+
}
|
|
228
|
+
if (this.pathCache[path5]) {
|
|
229
|
+
return this.pathCache[path5];
|
|
230
|
+
}
|
|
231
|
+
const pathname = new URL(path5, "https://example.com").pathname;
|
|
232
|
+
for (const [name, application] of Object.entries(this.applications)) {
|
|
233
|
+
if (application.routing) {
|
|
234
|
+
for (const group of application.routing) {
|
|
235
|
+
for (const childPath of group.paths) {
|
|
236
|
+
const regexp = (0, import_path_to_regexp.pathToRegexp)(childPath);
|
|
237
|
+
if (regexp.test(pathname)) {
|
|
238
|
+
this.pathCache[path5] = name;
|
|
239
|
+
return name;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
180
242
|
}
|
|
181
243
|
}
|
|
182
|
-
tag = args.join(options.joinString);
|
|
183
|
-
tag = tag.replace(/\s/g, options.joinString);
|
|
184
|
-
if (options.lowercaseOnly)
|
|
185
|
-
tag = tag.toLowerCase();
|
|
186
|
-
tag = tag.replace(options.regexRemovePattern, (match) => {
|
|
187
|
-
if (match === options.joinString)
|
|
188
|
-
return match;
|
|
189
|
-
return "";
|
|
190
|
-
});
|
|
191
|
-
if (tag.length > options.maxLen)
|
|
192
|
-
tag = tag.substring(0, options.maxLen);
|
|
193
|
-
tag = tag.replace(reJoinString, options.joinString);
|
|
194
|
-
return tag;
|
|
195
244
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
|
|
205
|
-
var _Overrides = class {
|
|
206
|
-
constructor(config) {
|
|
207
|
-
this.config = config;
|
|
245
|
+
const defaultApplication = Object.entries(this.applications).find(
|
|
246
|
+
([, application]) => application.default
|
|
247
|
+
);
|
|
248
|
+
if (!defaultApplication) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
this.pathCache[path5] = defaultApplication[0];
|
|
252
|
+
return defaultApplication[0];
|
|
208
253
|
}
|
|
209
|
-
|
|
210
|
-
return
|
|
254
|
+
serialize() {
|
|
255
|
+
return this.serialized;
|
|
211
256
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// src/config/microfrontends-config/isomorphic/validation.ts
|
|
260
|
+
var import_path_to_regexp2 = require("path-to-regexp");
|
|
261
|
+
var SUPPORTED_VERSIONS = ["2"];
|
|
262
|
+
var validateConfigVersion = (version) => {
|
|
263
|
+
if (!SUPPORTED_VERSIONS.includes(version)) {
|
|
264
|
+
throw new MicrofrontendError(
|
|
265
|
+
`Unsupported version: ${version}. Supported versions are: ${SUPPORTED_VERSIONS.join(
|
|
266
|
+
", "
|
|
267
|
+
)}`,
|
|
268
|
+
{ type: "config", subtype: "unsupported_version" }
|
|
269
|
+
);
|
|
215
270
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
return
|
|
220
|
-
zone: cookie.name.replace(_Overrides.overrideEnvCookiePrefix, ""),
|
|
221
|
-
host: cookie.value
|
|
222
|
-
};
|
|
271
|
+
};
|
|
272
|
+
var validateConfigPaths = (applicationConfigsById) => {
|
|
273
|
+
if (!applicationConfigsById) {
|
|
274
|
+
return;
|
|
223
275
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
276
|
+
const pathsByApplicationId = /* @__PURE__ */ new Map();
|
|
277
|
+
const errors = [];
|
|
278
|
+
for (const [id, app] of Object.entries(applicationConfigsById)) {
|
|
279
|
+
if (isDefaultApp(app)) {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
for (const pathMatch of app.routing) {
|
|
283
|
+
for (const path5 of pathMatch.paths) {
|
|
284
|
+
const maybeError = validatePathExpression(path5);
|
|
285
|
+
if (maybeError) {
|
|
286
|
+
errors.push(maybeError);
|
|
287
|
+
}
|
|
288
|
+
const existing = pathsByApplicationId.get(path5);
|
|
289
|
+
if (existing) {
|
|
290
|
+
existing.applications.push(id);
|
|
291
|
+
} else {
|
|
292
|
+
pathsByApplicationId.set(path5, {
|
|
293
|
+
applications: [id],
|
|
294
|
+
matcher: (0, import_path_to_regexp2.pathToRegexp)(path5),
|
|
295
|
+
applicationId: id
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
const entries = Array.from(pathsByApplicationId.entries());
|
|
302
|
+
entries.forEach(([path5, { applications: ids, matcher, applicationId }]) => {
|
|
303
|
+
if (ids.length > 1) {
|
|
304
|
+
errors.push(
|
|
305
|
+
`Duplicate path "${path5}" for applications "${ids.join(", ")}"`
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
entries.forEach(
|
|
309
|
+
([
|
|
310
|
+
matchPath,
|
|
311
|
+
{ applications: matchIds, applicationId: matchApplicationId }
|
|
312
|
+
]) => {
|
|
313
|
+
if (path5 === matchPath) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
if (applicationId === matchApplicationId) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (matcher.test(matchPath)) {
|
|
320
|
+
const source = `"${path5}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
321
|
+
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
322
|
+
errors.push(
|
|
323
|
+
`Overlapping path detected between ${source} and ${destination}`
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
});
|
|
329
|
+
if (errors.length) {
|
|
330
|
+
throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
|
|
331
|
+
type: "config",
|
|
332
|
+
subtype: "conflicting_paths"
|
|
233
333
|
});
|
|
234
|
-
return overridesConfig;
|
|
235
334
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
335
|
+
};
|
|
336
|
+
var PATH_DEFAULT_PATTERN = "[^\\/#\\?]+?";
|
|
337
|
+
function validatePathExpression(path5) {
|
|
338
|
+
const tokens = (0, import_path_to_regexp2.parse)(path5);
|
|
339
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
340
|
+
const token = tokens[i];
|
|
341
|
+
if (token === void 0) {
|
|
342
|
+
return `token ${i} in ${path5} is undefined, this shouldn't happen`;
|
|
343
|
+
}
|
|
344
|
+
if (typeof token !== "string") {
|
|
345
|
+
if (token.pattern !== PATH_DEFAULT_PATTERN) {
|
|
346
|
+
return `Path ${path5} cannot use a regular expression wildcard`;
|
|
347
|
+
}
|
|
348
|
+
if (token.prefix !== "/") {
|
|
349
|
+
return `Wildcard :${token.name} must be immediately after a / in ${path5}`;
|
|
350
|
+
}
|
|
351
|
+
if (token.suffix) {
|
|
352
|
+
return `Wildcard suffix on :${token.name} is not allowed. Suffixes are not supported`;
|
|
353
|
+
}
|
|
354
|
+
if (token.modifier && i !== tokens.length - 1) {
|
|
355
|
+
return `Modifier ${token.modifier} is not allowed on wildcard :${token.name} in ${path5}. Modifiers are only allowed in the last path component`;
|
|
356
|
+
}
|
|
241
357
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
358
|
+
}
|
|
359
|
+
return void 0;
|
|
360
|
+
}
|
|
361
|
+
var validateAppPaths = (name, app) => {
|
|
362
|
+
for (const group of app.routing) {
|
|
363
|
+
for (const p of group.paths) {
|
|
364
|
+
if (p === "/") {
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (p.endsWith("/")) {
|
|
368
|
+
throw new MicrofrontendError(
|
|
369
|
+
`Invalid path for application "${name}". ${p} must not end with a slash.`,
|
|
370
|
+
{ type: "application", subtype: "invalid_path" }
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
if (!p.startsWith("/")) {
|
|
374
|
+
throw new MicrofrontendError(
|
|
375
|
+
`Invalid path for application "${name}". ${p} must start with a slash.`,
|
|
376
|
+
{ type: "application", subtype: "invalid_path" }
|
|
377
|
+
);
|
|
378
|
+
}
|
|
247
379
|
}
|
|
248
|
-
const suffix = previewDeploymentSuffix ? `.${previewDeploymentSuffix}` : `-${teamSlug}.vercel.app`;
|
|
249
|
-
return [
|
|
250
|
-
`${parsedProjectName}-git-([a-zA-Z0-9-]+)${suffix}`,
|
|
251
|
-
microfrontendConfig.getZone(zone).production.host
|
|
252
|
-
];
|
|
253
380
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
)}$`
|
|
259
|
-
).test(domain);
|
|
381
|
+
};
|
|
382
|
+
var validateConfigDefaultApplication = (applicationConfigsById) => {
|
|
383
|
+
if (!applicationConfigsById) {
|
|
384
|
+
return;
|
|
260
385
|
}
|
|
261
|
-
|
|
262
|
-
|
|
386
|
+
const applicationsWithRouting = Object.entries(applicationConfigsById).filter(
|
|
387
|
+
([, app]) => !isDefaultApp(app)
|
|
388
|
+
);
|
|
389
|
+
const applicationsWithRoutingNames = applicationsWithRouting.map(
|
|
390
|
+
([key]) => key
|
|
391
|
+
);
|
|
392
|
+
const numApplications = Object.keys(applicationConfigsById).length;
|
|
393
|
+
const numApplicationsWithRouting = applicationsWithRoutingNames.length;
|
|
394
|
+
const numApplicationsWithoutRouting = numApplications - numApplicationsWithRouting;
|
|
395
|
+
if (numApplicationsWithoutRouting === 0) {
|
|
396
|
+
throw new MicrofrontendError(
|
|
397
|
+
`No default application found. At least one application needs to be the default by omitting routing.`,
|
|
398
|
+
{ type: "config", subtype: "no_default_application" }
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
if (numApplicationsWithoutRouting > 1) {
|
|
402
|
+
throw new MicrofrontendError(
|
|
403
|
+
`Only one application can omit "routing". Found ${applicationsWithRoutingNames.length - Object.keys(applicationConfigsById).length > 1}.`,
|
|
404
|
+
{ type: "config", subtype: "multiple_default_applications" }
|
|
405
|
+
);
|
|
263
406
|
}
|
|
264
407
|
};
|
|
265
|
-
var Overrides = _Overrides;
|
|
266
|
-
Overrides.overrideEnvCookiePrefix = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
267
408
|
|
|
268
|
-
// src/config/
|
|
409
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
|
|
410
|
+
var PREFIX = "vc-ap";
|
|
411
|
+
function generateAssetPrefixFromName({
|
|
412
|
+
name
|
|
413
|
+
}) {
|
|
414
|
+
if (!name) {
|
|
415
|
+
throw new Error("Name is required to generate an asset prefix");
|
|
416
|
+
}
|
|
417
|
+
return `${PREFIX}-${name}`;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-port.ts
|
|
421
|
+
function generatePortFromName({
|
|
422
|
+
name,
|
|
423
|
+
minPort = 3e3,
|
|
424
|
+
maxPort = 8e3
|
|
425
|
+
}) {
|
|
426
|
+
if (!name) {
|
|
427
|
+
throw new Error("Name is required to generate a port");
|
|
428
|
+
}
|
|
429
|
+
let hash = 0;
|
|
430
|
+
for (let i = 0; i < name.length; i++) {
|
|
431
|
+
hash = (hash << 5) - hash + name.charCodeAt(i);
|
|
432
|
+
hash |= 0;
|
|
433
|
+
}
|
|
434
|
+
hash = Math.abs(hash);
|
|
435
|
+
const range = maxPort - minPort;
|
|
436
|
+
const port = minPort + hash % range;
|
|
437
|
+
return port;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// src/config/microfrontends-config/isomorphic/host.ts
|
|
269
441
|
var Host = class {
|
|
270
|
-
constructor(
|
|
271
|
-
|
|
442
|
+
constructor(hostConfig, options) {
|
|
443
|
+
const { protocol = "https", host, port } = hostConfig;
|
|
444
|
+
this.protocol = protocol;
|
|
272
445
|
this.host = host;
|
|
273
446
|
this.port = Host.getPort({ port, protocol: this.protocol });
|
|
274
|
-
this.
|
|
275
|
-
protocol,
|
|
276
|
-
host,
|
|
277
|
-
...port ? { port } : void 0
|
|
278
|
-
};
|
|
447
|
+
this.local = options == null ? void 0 : options.isLocal;
|
|
279
448
|
}
|
|
280
449
|
isLocal() {
|
|
281
|
-
return this.host === "localhost" || this.host === "127.0.0.1";
|
|
450
|
+
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
282
451
|
}
|
|
283
452
|
static getPort({
|
|
284
453
|
protocol,
|
|
@@ -304,176 +473,234 @@ var Host = class {
|
|
|
304
473
|
const url = `${this.protocol}://${this.host}${this.isDefaultPort() && !includeDefaultPort ? "" : `:${this.port}`}`;
|
|
305
474
|
return new URL(url);
|
|
306
475
|
}
|
|
307
|
-
|
|
308
|
-
|
|
476
|
+
};
|
|
477
|
+
var LocalHost = class extends Host {
|
|
478
|
+
constructor({
|
|
479
|
+
appName,
|
|
480
|
+
...hostConfig
|
|
481
|
+
}) {
|
|
482
|
+
const host = hostConfig.host ?? "localhost";
|
|
483
|
+
const port = hostConfig.port ?? generatePortFromName({ name: appName });
|
|
484
|
+
const protocol = hostConfig.protocol ?? "http";
|
|
485
|
+
super({ protocol, host, port });
|
|
309
486
|
}
|
|
310
487
|
};
|
|
311
488
|
|
|
312
|
-
// src/config/
|
|
489
|
+
// src/config/microfrontends-config/isomorphic/application.ts
|
|
313
490
|
var Application = class {
|
|
314
491
|
constructor(name, {
|
|
315
492
|
app,
|
|
316
|
-
overrides
|
|
493
|
+
overrides,
|
|
494
|
+
isDefault
|
|
317
495
|
}) {
|
|
318
|
-
|
|
496
|
+
var _a, _b;
|
|
319
497
|
this.name = name;
|
|
320
|
-
this.default = app.default;
|
|
321
|
-
this.routing = app.routing;
|
|
322
498
|
this.development = {
|
|
323
|
-
local: new
|
|
324
|
-
|
|
499
|
+
local: new LocalHost({
|
|
500
|
+
appName: name,
|
|
501
|
+
...(_a = app.development) == null ? void 0 : _a.local
|
|
502
|
+
}),
|
|
503
|
+
fallback: ((_b = app.development) == null ? void 0 : _b.fallback) ? new Host(app.development.fallback) : void 0
|
|
325
504
|
};
|
|
326
|
-
this.production = new Host(app.production);
|
|
505
|
+
this.production = app.production ? new Host(app.production) : void 0;
|
|
327
506
|
this.vercel = app.vercel;
|
|
328
507
|
this.overrides = (overrides == null ? void 0 : overrides.environment) ? {
|
|
329
508
|
environment: new Host(overrides.environment)
|
|
330
509
|
} : void 0;
|
|
510
|
+
this.default = isDefault ?? false;
|
|
511
|
+
this.serialized = app;
|
|
331
512
|
}
|
|
332
513
|
isDefault() {
|
|
333
514
|
return this.default;
|
|
334
515
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
if (((_b = (_a = app.routing) == null ? void 0 : _a.assetPrefix) == null ? void 0 : _b.startsWith("/")) || ((_d = (_c = app.routing) == null ? void 0 : _c.assetPrefix) == null ? void 0 : _d.endsWith("/"))) {
|
|
338
|
-
throw new MicrofrontendError(
|
|
339
|
-
`Invalid assetPrefix for application "${name}". Must not start or end with a slash.`,
|
|
340
|
-
{ type: "zone", subtype: "invalid_asset_prefix" }
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
for (const group of ((_e = app.routing) == null ? void 0 : _e.matches) ?? []) {
|
|
344
|
-
for (const p of group.paths) {
|
|
345
|
-
if (p === "/") {
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
348
|
-
if (p.endsWith("/")) {
|
|
349
|
-
throw new MicrofrontendError(
|
|
350
|
-
`Invalid path for application "${name}". ${p} must not end with a slash.`,
|
|
351
|
-
{ type: "zone", subtype: "invalid_path" }
|
|
352
|
-
);
|
|
353
|
-
}
|
|
354
|
-
if (!p.startsWith("/")) {
|
|
355
|
-
throw new MicrofrontendError(
|
|
356
|
-
`Invalid path for application "${name}". ${p} must start with a slash.`,
|
|
357
|
-
{ type: "zone", subtype: "invalid_path" }
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
516
|
+
getAssetPrefix() {
|
|
517
|
+
return generateAssetPrefixFromName({ name: this.name });
|
|
362
518
|
}
|
|
363
519
|
serialize() {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
520
|
+
return this.serialized;
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
var DefaultApplication = class extends Application {
|
|
524
|
+
constructor(name, {
|
|
525
|
+
app,
|
|
526
|
+
overrides
|
|
527
|
+
}) {
|
|
528
|
+
super(name, {
|
|
529
|
+
app,
|
|
530
|
+
overrides,
|
|
531
|
+
isDefault: true
|
|
532
|
+
});
|
|
533
|
+
this.default = true;
|
|
534
|
+
this.production = new Host(app.production);
|
|
535
|
+
}
|
|
536
|
+
getAssetPrefix() {
|
|
537
|
+
return "";
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
var ChildApplication = class extends Application {
|
|
541
|
+
constructor(name, {
|
|
542
|
+
app,
|
|
543
|
+
overrides
|
|
544
|
+
}) {
|
|
545
|
+
ChildApplication.validate(name, app);
|
|
546
|
+
super(name, {
|
|
547
|
+
app,
|
|
548
|
+
overrides,
|
|
549
|
+
isDefault: false
|
|
550
|
+
});
|
|
551
|
+
this.default = false;
|
|
552
|
+
this.routing = app.routing;
|
|
553
|
+
}
|
|
554
|
+
static validate(name, app) {
|
|
555
|
+
validateAppPaths(name, app);
|
|
386
556
|
}
|
|
387
557
|
};
|
|
388
558
|
|
|
389
|
-
// src/config/
|
|
390
|
-
var SUPPORTED_VERSIONS = ["1"];
|
|
559
|
+
// src/config/microfrontends-config/isomorphic/constants.ts
|
|
391
560
|
var DEFAULT_LOCAL_PROXY_PORT = 3024;
|
|
392
|
-
|
|
561
|
+
|
|
562
|
+
// src/config/microfrontends-config/isomorphic/index.ts
|
|
563
|
+
var MicrofrontendConfigIsomorphic = class {
|
|
393
564
|
constructor({
|
|
394
565
|
config,
|
|
395
|
-
overrides
|
|
566
|
+
overrides,
|
|
567
|
+
meta
|
|
396
568
|
}) {
|
|
397
|
-
this.
|
|
398
|
-
var _a, _b, _c;
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
569
|
+
this.childApplications = {};
|
|
570
|
+
var _a, _b, _c, _d;
|
|
571
|
+
MicrofrontendConfigIsomorphic.validate(config);
|
|
572
|
+
const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
573
|
+
this.overrides = overrides && !disableOverrides ? overrides : void 0;
|
|
574
|
+
this.isMainConfig = isMainConfig(config);
|
|
575
|
+
if (isMainConfig(config)) {
|
|
576
|
+
for (const [appId, appConfig] of Object.entries(config.applications)) {
|
|
577
|
+
const appOverrides = !disableOverrides ? (_c = this.overrides) == null ? void 0 : _c.applications[appId] : void 0;
|
|
578
|
+
if (isDefaultApp(appConfig)) {
|
|
579
|
+
this.defaultApplication = new DefaultApplication(appId, {
|
|
580
|
+
app: appConfig,
|
|
581
|
+
overrides: appOverrides
|
|
582
|
+
});
|
|
583
|
+
} else {
|
|
584
|
+
this.childApplications[appId] = new ChildApplication(appId, {
|
|
585
|
+
app: appConfig,
|
|
586
|
+
overrides: appOverrides
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
} else {
|
|
591
|
+
this.partOf = config.partOf;
|
|
592
|
+
const appOverrides = !disableOverrides ? (_d = this.overrides) == null ? void 0 : _d.applications[meta.fromApp] : void 0;
|
|
593
|
+
this.childApplications[meta.fromApp] = new ChildApplication(
|
|
594
|
+
meta.fromApp,
|
|
595
|
+
{
|
|
596
|
+
// we don't know routing because we're not in the main config
|
|
597
|
+
app: { routing: [] },
|
|
598
|
+
overrides: appOverrides
|
|
599
|
+
}
|
|
405
600
|
);
|
|
406
601
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
602
|
+
if (isMainConfig(config) && !this.defaultApplication) {
|
|
603
|
+
throw new MicrofrontendError(
|
|
604
|
+
`Could not find default application in microfrontends configuration`,
|
|
605
|
+
{
|
|
606
|
+
type: "application",
|
|
607
|
+
subtype: "not_found"
|
|
608
|
+
}
|
|
609
|
+
);
|
|
414
610
|
}
|
|
415
611
|
this.config = config;
|
|
416
|
-
this.name = config.name;
|
|
417
|
-
this.version = config.version;
|
|
418
612
|
this.options = config.options;
|
|
419
|
-
this
|
|
613
|
+
this.serialized = {
|
|
614
|
+
config,
|
|
615
|
+
overrides,
|
|
616
|
+
meta
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
static validate(config) {
|
|
620
|
+
const c = typeof config === "string" ? (0, import_jsonc_parser.parse)(config) : config;
|
|
621
|
+
if (isMainConfig(c)) {
|
|
622
|
+
validateConfigVersion(c.version);
|
|
623
|
+
validateConfigPaths(c.applications);
|
|
624
|
+
validateConfigDefaultApplication(c.applications);
|
|
625
|
+
}
|
|
626
|
+
return c;
|
|
627
|
+
}
|
|
628
|
+
static fromEnv({
|
|
629
|
+
meta,
|
|
630
|
+
cookies
|
|
631
|
+
}) {
|
|
632
|
+
return new MicrofrontendConfigIsomorphic({
|
|
633
|
+
config: (0, import_jsonc_parser.parse)(getConfigStringFromEnv()),
|
|
634
|
+
overrides: parseOverrides(cookies ?? []),
|
|
635
|
+
meta
|
|
636
|
+
});
|
|
420
637
|
}
|
|
421
638
|
isOverridesDisabled() {
|
|
422
639
|
var _a, _b;
|
|
423
640
|
return ((_b = (_a = this.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
424
641
|
}
|
|
425
|
-
static getConfigFromEnv() {
|
|
426
|
-
const config = process.env.MFE_CONFIG;
|
|
427
|
-
if (!config) {
|
|
428
|
-
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
429
|
-
type: "config",
|
|
430
|
-
subtype: "not_found_in_env"
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
return config;
|
|
434
|
-
}
|
|
435
|
-
static fromEnv(_) {
|
|
436
|
-
throw new Error("Not implemented");
|
|
437
|
-
}
|
|
438
642
|
getConfig() {
|
|
439
643
|
return this.config;
|
|
440
644
|
}
|
|
441
|
-
|
|
442
|
-
return
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
645
|
+
getApplicationsByType() {
|
|
646
|
+
return {
|
|
647
|
+
defaultApplication: this.defaultApplication,
|
|
648
|
+
applications: Object.values(this.childApplications)
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
getChildApplications() {
|
|
652
|
+
return Object.values(this.childApplications);
|
|
653
|
+
}
|
|
654
|
+
getAllApplications() {
|
|
655
|
+
return [
|
|
656
|
+
this.defaultApplication,
|
|
657
|
+
...Object.values(this.childApplications)
|
|
658
|
+
].filter(Boolean);
|
|
659
|
+
}
|
|
660
|
+
getApplication(name) {
|
|
661
|
+
var _a;
|
|
662
|
+
if (((_a = this.defaultApplication) == null ? void 0 : _a.name) === name) {
|
|
663
|
+
return this.defaultApplication;
|
|
664
|
+
}
|
|
665
|
+
const app = this.childApplications[name];
|
|
666
|
+
if (!app) {
|
|
447
667
|
throw new MicrofrontendError(
|
|
448
668
|
`Could not find microfrontends configuration for application "${name}"`,
|
|
449
669
|
{
|
|
450
|
-
type: "
|
|
670
|
+
type: "application",
|
|
451
671
|
subtype: "not_found"
|
|
452
672
|
}
|
|
453
673
|
);
|
|
454
674
|
}
|
|
455
|
-
return
|
|
675
|
+
return app;
|
|
456
676
|
}
|
|
457
677
|
getApplicationByProjectId(projectId) {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
678
|
+
var _a, _b;
|
|
679
|
+
if (((_b = (_a = this.defaultApplication) == null ? void 0 : _a.vercel) == null ? void 0 : _b.projectId) === projectId) {
|
|
680
|
+
return this.defaultApplication;
|
|
681
|
+
}
|
|
682
|
+
return Object.values(this.childApplications).find(
|
|
683
|
+
(app) => {
|
|
684
|
+
var _a2;
|
|
685
|
+
return ((_a2 = app.vercel) == null ? void 0 : _a2.projectId) === projectId;
|
|
462
686
|
}
|
|
463
687
|
);
|
|
464
688
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
689
|
+
/**
|
|
690
|
+
* Returns the default application. This can throw if the default application
|
|
691
|
+
* is undefined ( )
|
|
692
|
+
*/
|
|
693
|
+
getDefaultApplication() {
|
|
694
|
+
if (!this.defaultApplication) {
|
|
468
695
|
throw new MicrofrontendError(
|
|
469
|
-
`Could not find default
|
|
696
|
+
`Could not find default application in microfrontends configuration`,
|
|
470
697
|
{
|
|
471
|
-
type: "
|
|
698
|
+
type: "application",
|
|
472
699
|
subtype: "not_found"
|
|
473
700
|
}
|
|
474
701
|
);
|
|
475
702
|
}
|
|
476
|
-
return
|
|
703
|
+
return this.defaultApplication;
|
|
477
704
|
}
|
|
478
705
|
/**
|
|
479
706
|
* Returns the configured port for the local proxy
|
|
@@ -488,671 +715,801 @@ var MicrofrontendConfigCommon = class {
|
|
|
488
715
|
* NOTE: This is used when writing the config to disk and must always match the input Schema
|
|
489
716
|
*/
|
|
490
717
|
toSchemaJson() {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
718
|
+
return this.serialized.config;
|
|
719
|
+
}
|
|
720
|
+
toClientConfig() {
|
|
721
|
+
const applications = Object.fromEntries(
|
|
722
|
+
Object.entries(this.childApplications).map(([name, application]) => [
|
|
723
|
+
name,
|
|
724
|
+
{
|
|
725
|
+
default: false,
|
|
726
|
+
routing: application.routing
|
|
727
|
+
}
|
|
728
|
+
])
|
|
729
|
+
);
|
|
730
|
+
if (this.defaultApplication) {
|
|
731
|
+
applications[this.defaultApplication.name] = {
|
|
732
|
+
default: true
|
|
733
|
+
};
|
|
494
734
|
}
|
|
495
|
-
return {
|
|
496
|
-
$schema: this.$schema,
|
|
497
|
-
name: this.name,
|
|
498
|
-
version: this.version,
|
|
499
|
-
options: this.options,
|
|
735
|
+
return new MicrofrontendConfigClient({
|
|
500
736
|
applications
|
|
501
|
-
};
|
|
737
|
+
});
|
|
502
738
|
}
|
|
503
739
|
serialize() {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
740
|
+
return this.serialized;
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
|
|
744
|
+
// src/config/microfrontends-config/isomorphic/child.ts
|
|
745
|
+
var MicrofrontendChildConfig = class extends MicrofrontendConfigIsomorphic {
|
|
746
|
+
constructor({
|
|
747
|
+
config,
|
|
748
|
+
overrides,
|
|
749
|
+
meta
|
|
750
|
+
}) {
|
|
751
|
+
super({ config, overrides, meta });
|
|
752
|
+
this.isMainConfig = false;
|
|
753
|
+
this.partOf = config.partOf;
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
// src/config/microfrontends-config/isomorphic/main.ts
|
|
758
|
+
var MicrofrontendMainConfig = class extends MicrofrontendConfigIsomorphic {
|
|
759
|
+
constructor({
|
|
760
|
+
config,
|
|
761
|
+
overrides,
|
|
762
|
+
meta
|
|
763
|
+
}) {
|
|
764
|
+
var _a, _b, _c;
|
|
765
|
+
super({ config, overrides, meta });
|
|
766
|
+
this.isMainConfig = true;
|
|
767
|
+
const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
768
|
+
let defaultApplication;
|
|
769
|
+
for (const [appId, appConfig] of Object.entries(config.applications)) {
|
|
770
|
+
const appOverrides = !disableOverrides ? (_c = this.overrides) == null ? void 0 : _c.applications[appId] : void 0;
|
|
771
|
+
if (isDefaultApp(appConfig)) {
|
|
772
|
+
defaultApplication = new DefaultApplication(appId, {
|
|
773
|
+
app: appConfig,
|
|
774
|
+
overrides: appOverrides
|
|
775
|
+
});
|
|
776
|
+
} else {
|
|
777
|
+
this.childApplications[appId] = new ChildApplication(appId, {
|
|
778
|
+
app: appConfig,
|
|
779
|
+
overrides: appOverrides
|
|
780
|
+
});
|
|
781
|
+
}
|
|
508
782
|
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
783
|
+
if (!defaultApplication) {
|
|
784
|
+
throw new MicrofrontendError(
|
|
785
|
+
`Could not find default application in microfrontends configuration`,
|
|
786
|
+
{
|
|
787
|
+
type: "application",
|
|
788
|
+
subtype: "not_found"
|
|
789
|
+
}
|
|
790
|
+
);
|
|
791
|
+
}
|
|
792
|
+
this.defaultApplication = defaultApplication;
|
|
519
793
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
// src/config/microfrontends/isomorphic/index.ts
|
|
797
|
+
var Microfrontends = class {
|
|
798
|
+
constructor({
|
|
799
|
+
config,
|
|
800
|
+
overrides,
|
|
801
|
+
meta
|
|
802
|
+
}) {
|
|
803
|
+
if (isMainConfig(config)) {
|
|
804
|
+
this.config = new MicrofrontendMainConfig({ config, overrides, meta });
|
|
805
|
+
} else {
|
|
806
|
+
this.config = new MicrofrontendChildConfig({ config, overrides, meta });
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
isChildConfig() {
|
|
810
|
+
return this.config instanceof MicrofrontendChildConfig;
|
|
811
|
+
}
|
|
812
|
+
static fromEnv({
|
|
813
|
+
cookies,
|
|
814
|
+
meta
|
|
815
|
+
}) {
|
|
816
|
+
const config = MicrofrontendConfigIsomorphic.fromEnv({
|
|
817
|
+
cookies,
|
|
818
|
+
meta
|
|
819
|
+
});
|
|
820
|
+
return new Microfrontends(config.serialize());
|
|
525
821
|
}
|
|
526
822
|
};
|
|
527
823
|
|
|
528
|
-
// src/config/utils/
|
|
529
|
-
var
|
|
824
|
+
// src/config/microfrontends/utils/find-repository-root.ts
|
|
825
|
+
var import_node_fs = __toESM(require("fs"), 1);
|
|
826
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
827
|
+
var GIT_DIRECTORY = ".git";
|
|
828
|
+
function findRepositoryRoot(startDir) {
|
|
829
|
+
let currentDir = startDir || process.cwd();
|
|
830
|
+
while (currentDir !== import_node_path.default.parse(currentDir).root) {
|
|
831
|
+
const gitPath = import_node_path.default.join(currentDir, GIT_DIRECTORY);
|
|
832
|
+
if (import_node_fs.default.existsSync(gitPath) && import_node_fs.default.statSync(gitPath).isDirectory()) {
|
|
833
|
+
return currentDir;
|
|
834
|
+
}
|
|
835
|
+
currentDir = import_node_path.default.dirname(currentDir);
|
|
836
|
+
}
|
|
837
|
+
throw new Error(
|
|
838
|
+
"Repository root not found. Specify the root of the repository with the `repository.root` option."
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// src/config/microfrontends/utils/find-package-path.ts
|
|
843
|
+
var import_node_path2 = require("path");
|
|
844
|
+
var import_node_fs2 = require("fs");
|
|
845
|
+
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
846
|
+
var configCache = {};
|
|
847
|
+
function findPackagePathWithGlob({
|
|
848
|
+
repositoryRoot,
|
|
849
|
+
name
|
|
850
|
+
}) {
|
|
851
|
+
try {
|
|
852
|
+
const packageJsonPaths = import_fast_glob.default.globSync("**/package.json", {
|
|
853
|
+
cwd: repositoryRoot,
|
|
854
|
+
absolute: true,
|
|
855
|
+
onlyFiles: true,
|
|
856
|
+
followSymbolicLinks: false,
|
|
857
|
+
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
858
|
+
});
|
|
859
|
+
const matchingPaths = [];
|
|
860
|
+
for (const packageJsonPath2 of packageJsonPaths) {
|
|
861
|
+
const packageJsonContent = (0, import_node_fs2.readFileSync)(packageJsonPath2, "utf-8");
|
|
862
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
863
|
+
if (packageJson.name === name) {
|
|
864
|
+
matchingPaths.push(packageJsonPath2);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
if (matchingPaths.length > 1) {
|
|
868
|
+
throw new Error(
|
|
869
|
+
`Found multiple packages with the name "${name}" in the repository: ${matchingPaths.join(", ")}`
|
|
870
|
+
);
|
|
871
|
+
}
|
|
872
|
+
if (matchingPaths.length === 0) {
|
|
873
|
+
throw new Error(
|
|
874
|
+
`Could not find package with the name "${name}" in the repository`
|
|
875
|
+
);
|
|
876
|
+
}
|
|
877
|
+
const [packageJsonPath] = matchingPaths;
|
|
878
|
+
return (0, import_node_path2.dirname)(packageJsonPath);
|
|
879
|
+
} catch (error) {
|
|
880
|
+
return null;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
function findPackagePath(opts) {
|
|
884
|
+
const cacheKey = `${opts.repositoryRoot}-${opts.name}`;
|
|
885
|
+
if (configCache[cacheKey]) {
|
|
886
|
+
return configCache[cacheKey];
|
|
887
|
+
}
|
|
888
|
+
const result = findPackagePathWithGlob(opts);
|
|
889
|
+
if (!result) {
|
|
890
|
+
throw new Error(
|
|
891
|
+
`Could not find package with the name "${opts.name}" in the repository`
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
configCache[cacheKey] = result;
|
|
895
|
+
return result;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// src/config/microfrontends/utils/find-default-package.ts
|
|
899
|
+
var import_node_path3 = require("path");
|
|
900
|
+
var import_node_fs3 = require("fs");
|
|
901
|
+
var import_jsonc_parser2 = require("jsonc-parser");
|
|
902
|
+
var import_fast_glob2 = __toESM(require("fast-glob"), 1);
|
|
530
903
|
|
|
531
904
|
// src/config/constants.ts
|
|
532
|
-
var
|
|
533
|
-
|
|
905
|
+
var CONFIGURATION_FILENAMES = [
|
|
906
|
+
"microfrontends.jsonc",
|
|
907
|
+
"microfrontends.json"
|
|
908
|
+
];
|
|
534
909
|
|
|
535
|
-
// src/config/utils/
|
|
536
|
-
|
|
910
|
+
// src/config/microfrontends/utils/find-default-package.ts
|
|
911
|
+
var configCache2 = {};
|
|
912
|
+
function findDefaultMicrofrontendsPackages({
|
|
913
|
+
repositoryRoot,
|
|
914
|
+
applicationName
|
|
915
|
+
}) {
|
|
916
|
+
try {
|
|
917
|
+
const microfrontendsJsonPaths = import_fast_glob2.default.globSync(
|
|
918
|
+
`**/{${CONFIGURATION_FILENAMES.join(",")}}`,
|
|
919
|
+
{
|
|
920
|
+
cwd: repositoryRoot,
|
|
921
|
+
absolute: true,
|
|
922
|
+
onlyFiles: true,
|
|
923
|
+
followSymbolicLinks: false,
|
|
924
|
+
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
925
|
+
}
|
|
926
|
+
);
|
|
927
|
+
const matchingPaths = [];
|
|
928
|
+
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
929
|
+
const microfrontendsJsonContent = (0, import_node_fs3.readFileSync)(
|
|
930
|
+
microfrontendsJsonPath,
|
|
931
|
+
"utf-8"
|
|
932
|
+
);
|
|
933
|
+
const microfrontendsJson = (0, import_jsonc_parser2.parse)(microfrontendsJsonContent);
|
|
934
|
+
if (isMainConfig(microfrontendsJson) && microfrontendsJson.applications[applicationName]) {
|
|
935
|
+
matchingPaths.push(microfrontendsJsonPath);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
if (matchingPaths.length > 1) {
|
|
939
|
+
throw new Error(
|
|
940
|
+
`Found multiple default applications referencing "${applicationName}" in the repository, this is not yet supported.
|
|
941
|
+
${matchingPaths.join("\n \u2022 ")}`
|
|
942
|
+
);
|
|
943
|
+
}
|
|
944
|
+
if (matchingPaths.length === 0) {
|
|
945
|
+
throw new Error(
|
|
946
|
+
`Could not find default application with "applications.${applicationName}"`
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
const [packageJsonPath] = matchingPaths;
|
|
950
|
+
return (0, import_node_path3.dirname)(packageJsonPath);
|
|
951
|
+
} catch (error) {
|
|
952
|
+
return null;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
function findDefaultMicrofrontendsPackage(opts) {
|
|
956
|
+
const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;
|
|
957
|
+
if (configCache2[cacheKey]) {
|
|
958
|
+
return configCache2[cacheKey];
|
|
959
|
+
}
|
|
960
|
+
const result = findDefaultMicrofrontendsPackages(opts);
|
|
961
|
+
if (!result) {
|
|
962
|
+
throw new Error(
|
|
963
|
+
`Error trying to resolve the main microfrontends configuration`
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
configCache2[cacheKey] = result;
|
|
967
|
+
return result;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// src/config/microfrontends/utils/is-monorepo.ts
|
|
971
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
972
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
973
|
+
function isMonorepo({
|
|
974
|
+
repositoryRoot
|
|
975
|
+
}) {
|
|
976
|
+
try {
|
|
977
|
+
if (import_node_fs4.default.existsSync(import_node_path4.default.join(repositoryRoot, "pnpm-workspace.yaml"))) {
|
|
978
|
+
return true;
|
|
979
|
+
}
|
|
980
|
+
if (import_node_fs4.default.existsSync(import_node_path4.default.join(repositoryRoot, "vlt-workspaces.json"))) {
|
|
981
|
+
return true;
|
|
982
|
+
}
|
|
983
|
+
const packageJsonPath = import_node_path4.default.join(repositoryRoot, "package.json");
|
|
984
|
+
if (!import_node_fs4.default.existsSync(packageJsonPath)) {
|
|
985
|
+
return false;
|
|
986
|
+
}
|
|
987
|
+
const packageJson = JSON.parse(
|
|
988
|
+
import_node_fs4.default.readFileSync(packageJsonPath, "utf-8")
|
|
989
|
+
);
|
|
990
|
+
return packageJson.workspaces !== void 0;
|
|
991
|
+
} catch (error) {
|
|
992
|
+
console.error("Error determining if repository is a monorepo", error);
|
|
993
|
+
return false;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// src/config/microfrontends/utils/find-package-root.ts
|
|
998
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
999
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
1000
|
+
var PACKAGE_JSON = "package.json";
|
|
1001
|
+
function findPackageRoot(startDir) {
|
|
1002
|
+
let currentDir = startDir || process.cwd();
|
|
1003
|
+
while (currentDir !== import_node_path5.default.parse(currentDir).root) {
|
|
1004
|
+
const pkgJsonPath = import_node_path5.default.join(currentDir, PACKAGE_JSON);
|
|
1005
|
+
if (import_node_fs5.default.existsSync(pkgJsonPath)) {
|
|
1006
|
+
return currentDir;
|
|
1007
|
+
}
|
|
1008
|
+
currentDir = import_node_path5.default.dirname(currentDir);
|
|
1009
|
+
}
|
|
1010
|
+
throw new Error(
|
|
1011
|
+
"Package root not found. Specify the root of the package with the `package.root` option."
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
// src/config/microfrontends/utils/find-config.ts
|
|
1016
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
1017
|
+
var import_node_path6 = require("path");
|
|
1018
|
+
function findConfig({ dir }) {
|
|
1019
|
+
for (const filename of CONFIGURATION_FILENAMES) {
|
|
1020
|
+
const maybeConfig = (0, import_node_path6.join)(dir, filename);
|
|
1021
|
+
if (import_node_fs6.default.existsSync(maybeConfig)) {
|
|
1022
|
+
return maybeConfig;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
return null;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// src/config/microfrontends/server/utils/get-output-file-path.ts
|
|
1029
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
1030
|
+
|
|
1031
|
+
// src/config/microfrontends/server/constants.ts
|
|
1032
|
+
var MFE_CONFIG_DEFAULT_FILE_PATH = "microfrontends";
|
|
1033
|
+
var MFE_CONFIG_DEFAULT_FILE_NAME = "microfrontends.json";
|
|
1034
|
+
|
|
1035
|
+
// src/utils/is-vercel.ts
|
|
1036
|
+
function isVercel() {
|
|
1037
|
+
return process.env.VERCEL === "1";
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
// src/config/microfrontends/server/utils/get-output-file-path.ts
|
|
1041
|
+
function getOutputFilePath() {
|
|
537
1042
|
if (isVercel()) {
|
|
538
|
-
return
|
|
1043
|
+
return import_node_path7.default.join(
|
|
539
1044
|
".vercel",
|
|
540
|
-
|
|
541
|
-
|
|
1045
|
+
MFE_CONFIG_DEFAULT_FILE_PATH,
|
|
1046
|
+
MFE_CONFIG_DEFAULT_FILE_NAME
|
|
542
1047
|
);
|
|
543
1048
|
}
|
|
544
|
-
return
|
|
1049
|
+
return import_node_path7.default.join(MFE_CONFIG_DEFAULT_FILE_PATH, MFE_CONFIG_DEFAULT_FILE_NAME);
|
|
545
1050
|
}
|
|
546
1051
|
|
|
547
|
-
// src/config/validation.ts
|
|
548
|
-
var
|
|
549
|
-
var import_path_to_regexp = require("path-to-regexp");
|
|
1052
|
+
// src/config/microfrontends/server/validation.ts
|
|
1053
|
+
var import_jsonc_parser3 = require("jsonc-parser");
|
|
550
1054
|
var import_ajv = require("ajv");
|
|
551
1055
|
|
|
552
|
-
// src/config/types.ts
|
|
553
|
-
var isDefaultApplicationConfig = (app) => app.default && typeof app.routing === "undefined";
|
|
554
|
-
|
|
555
1056
|
// schema/schema.json
|
|
556
1057
|
var schema_default = {
|
|
557
1058
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
558
1059
|
$ref: "#/definitions/Config",
|
|
559
1060
|
definitions: {
|
|
560
1061
|
Config: {
|
|
1062
|
+
anyOf: [
|
|
1063
|
+
{
|
|
1064
|
+
$ref: "#/definitions/MainConfig"
|
|
1065
|
+
},
|
|
1066
|
+
{
|
|
1067
|
+
$ref: "#/definitions/ChildConfig"
|
|
1068
|
+
}
|
|
1069
|
+
]
|
|
1070
|
+
},
|
|
1071
|
+
MainConfig: {
|
|
561
1072
|
type: "object",
|
|
562
1073
|
properties: {
|
|
563
|
-
version: {
|
|
564
|
-
type: "string"
|
|
565
|
-
},
|
|
566
1074
|
$schema: {
|
|
567
1075
|
type: "string"
|
|
568
1076
|
},
|
|
569
|
-
|
|
1077
|
+
version: {
|
|
570
1078
|
type: "string",
|
|
571
|
-
|
|
1079
|
+
const: "2"
|
|
1080
|
+
},
|
|
1081
|
+
options: {
|
|
1082
|
+
$ref: "#/definitions/Options"
|
|
1083
|
+
},
|
|
1084
|
+
remotes: {
|
|
1085
|
+
type: "object",
|
|
1086
|
+
additionalProperties: {
|
|
1087
|
+
$ref: "#/definitions/Application"
|
|
1088
|
+
},
|
|
1089
|
+
description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
|
|
572
1090
|
},
|
|
573
1091
|
applications: {
|
|
574
|
-
$ref: "#/definitions/
|
|
1092
|
+
$ref: "#/definitions/ApplicationRouting",
|
|
1093
|
+
description: "Mapping of application names to the routes that they host. Only needs to be defined in the application that owns the primary microfrontend domain"
|
|
1094
|
+
}
|
|
1095
|
+
},
|
|
1096
|
+
required: ["applications", "version"],
|
|
1097
|
+
additionalProperties: false
|
|
1098
|
+
},
|
|
1099
|
+
Options: {
|
|
1100
|
+
type: "object",
|
|
1101
|
+
properties: {
|
|
1102
|
+
vercel: {
|
|
1103
|
+
$ref: "#/definitions/VercelOptions",
|
|
1104
|
+
description: "Micro-Frontends wide options for Vercel."
|
|
575
1105
|
},
|
|
576
|
-
|
|
577
|
-
$ref: "#/definitions/
|
|
578
|
-
description: "
|
|
1106
|
+
localProxy: {
|
|
1107
|
+
$ref: "#/definitions/LocalProxyOptions",
|
|
1108
|
+
description: "Options for local proxy."
|
|
579
1109
|
}
|
|
580
1110
|
},
|
|
581
|
-
|
|
582
|
-
description: "Configuration for micro-frontend applications\n\nTODO: Add proxy configuration"
|
|
1111
|
+
additionalProperties: false
|
|
583
1112
|
},
|
|
584
|
-
|
|
1113
|
+
VercelOptions: {
|
|
585
1114
|
type: "object",
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
1115
|
+
properties: {
|
|
1116
|
+
teamSlug: {
|
|
1117
|
+
type: "string",
|
|
1118
|
+
description: "Team slug for the Vercel team"
|
|
1119
|
+
},
|
|
1120
|
+
disableOverrides: {
|
|
1121
|
+
type: "boolean",
|
|
1122
|
+
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."
|
|
1123
|
+
}
|
|
1124
|
+
},
|
|
1125
|
+
additionalProperties: false
|
|
589
1126
|
},
|
|
590
|
-
|
|
1127
|
+
LocalProxyOptions: {
|
|
1128
|
+
type: "object",
|
|
1129
|
+
properties: {
|
|
1130
|
+
port: {
|
|
1131
|
+
type: "number",
|
|
1132
|
+
description: "The port number used by the local proxy server.\n\nThe default is `3024`."
|
|
1133
|
+
}
|
|
1134
|
+
},
|
|
1135
|
+
additionalProperties: false
|
|
1136
|
+
},
|
|
1137
|
+
Application: {
|
|
591
1138
|
anyOf: [
|
|
592
1139
|
{
|
|
593
|
-
$ref: "#/definitions/
|
|
1140
|
+
$ref: "#/definitions/DefaultApplication"
|
|
594
1141
|
},
|
|
595
1142
|
{
|
|
596
|
-
$ref: "#/definitions/
|
|
1143
|
+
$ref: "#/definitions/ChildApplication"
|
|
597
1144
|
}
|
|
598
|
-
]
|
|
599
|
-
description: "A Micro-Frontend Deployment Target"
|
|
1145
|
+
]
|
|
600
1146
|
},
|
|
601
|
-
|
|
1147
|
+
DefaultApplication: {
|
|
602
1148
|
type: "object",
|
|
603
1149
|
properties: {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
const: true,
|
|
607
|
-
description: "The default application is used no other application is matched via the routing config"
|
|
608
|
-
},
|
|
609
|
-
routing: {
|
|
610
|
-
$ref: "#/definitions/Routing"
|
|
1150
|
+
vercel: {
|
|
1151
|
+
$ref: "#/definitions/Vercel"
|
|
611
1152
|
},
|
|
612
1153
|
development: {
|
|
613
|
-
|
|
614
|
-
properties: {
|
|
615
|
-
local: {
|
|
616
|
-
$ref: "#/definitions/HostConfig"
|
|
617
|
-
},
|
|
618
|
-
fallback: {
|
|
619
|
-
$ref: "#/definitions/HostConfig",
|
|
620
|
-
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."
|
|
621
|
-
},
|
|
622
|
-
task: {
|
|
623
|
-
type: "string",
|
|
624
|
-
description: "Optional task to run when starting the development server. Should reference a script in the package.json of the application."
|
|
625
|
-
}
|
|
626
|
-
},
|
|
627
|
-
required: ["local"]
|
|
1154
|
+
$ref: "#/definitions/Development"
|
|
628
1155
|
},
|
|
629
1156
|
production: {
|
|
630
1157
|
$ref: "#/definitions/HostConfig"
|
|
631
|
-
},
|
|
632
|
-
metadata: {
|
|
633
|
-
type: "object",
|
|
634
|
-
additionalProperties: {
|
|
635
|
-
type: "string"
|
|
636
|
-
}
|
|
637
|
-
},
|
|
638
|
-
federation: {
|
|
639
|
-
type: "object",
|
|
640
|
-
properties: {
|
|
641
|
-
exposes: {
|
|
642
|
-
type: "array",
|
|
643
|
-
items: {
|
|
644
|
-
type: "object",
|
|
645
|
-
properties: {
|
|
646
|
-
name: {
|
|
647
|
-
type: "string",
|
|
648
|
-
description: "The name of the module - should be used when importing the module from another application"
|
|
649
|
-
},
|
|
650
|
-
path: {
|
|
651
|
-
type: "string",
|
|
652
|
-
description: "Relative path to the module within its `application`"
|
|
653
|
-
}
|
|
654
|
-
},
|
|
655
|
-
required: ["name", "path"]
|
|
656
|
-
},
|
|
657
|
-
description: "Modules that are exposed by this application"
|
|
658
|
-
},
|
|
659
|
-
uses: {
|
|
660
|
-
type: "array",
|
|
661
|
-
items: {
|
|
662
|
-
type: "string"
|
|
663
|
-
},
|
|
664
|
-
description: "Modules that are used by this application. Only the name of the module is required."
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
},
|
|
668
|
-
vercel: {
|
|
669
|
-
$ref: "#/definitions/Vercel"
|
|
670
1158
|
}
|
|
671
1159
|
},
|
|
672
|
-
required: ["
|
|
1160
|
+
required: ["production"],
|
|
1161
|
+
additionalProperties: false
|
|
673
1162
|
},
|
|
674
|
-
|
|
1163
|
+
Vercel: {
|
|
675
1164
|
type: "object",
|
|
676
1165
|
properties: {
|
|
677
|
-
|
|
1166
|
+
projectId: {
|
|
678
1167
|
type: "string",
|
|
679
|
-
description: "
|
|
680
|
-
},
|
|
681
|
-
matches: {
|
|
682
|
-
type: "array",
|
|
683
|
-
items: {
|
|
684
|
-
$ref: "#/definitions/PathGroup"
|
|
685
|
-
},
|
|
686
|
-
description: "Path expressions that are routed to this application."
|
|
1168
|
+
description: "Vercel project ID"
|
|
687
1169
|
}
|
|
688
1170
|
},
|
|
689
|
-
required: ["
|
|
1171
|
+
required: ["projectId"],
|
|
1172
|
+
additionalProperties: false
|
|
690
1173
|
},
|
|
691
|
-
|
|
1174
|
+
Development: {
|
|
692
1175
|
type: "object",
|
|
693
1176
|
properties: {
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
description: "Optional group name for the paths"
|
|
1177
|
+
local: {
|
|
1178
|
+
$ref: "#/definitions/LocalHostConfig"
|
|
697
1179
|
},
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
flag: {
|
|
702
|
-
type: "string",
|
|
703
|
-
description: "flag name that can be used to enable/disable all paths in the group"
|
|
704
|
-
}
|
|
705
|
-
}
|
|
1180
|
+
fallback: {
|
|
1181
|
+
$ref: "#/definitions/HostConfig",
|
|
1182
|
+
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."
|
|
706
1183
|
},
|
|
707
|
-
|
|
708
|
-
type: "
|
|
709
|
-
|
|
710
|
-
type: "string"
|
|
711
|
-
}
|
|
1184
|
+
task: {
|
|
1185
|
+
type: "string",
|
|
1186
|
+
description: "Optional task to run when starting the development server. Should reference a script in the package.json of the application."
|
|
712
1187
|
}
|
|
713
1188
|
},
|
|
714
|
-
|
|
1189
|
+
additionalProperties: false
|
|
715
1190
|
},
|
|
716
|
-
|
|
1191
|
+
LocalHostConfig: {
|
|
717
1192
|
type: "object",
|
|
1193
|
+
additionalProperties: false,
|
|
718
1194
|
properties: {
|
|
719
|
-
protocol: {
|
|
720
|
-
type: "string",
|
|
721
|
-
enum: ["http", "https"],
|
|
722
|
-
description: 'The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n* @defaultValue "https"'
|
|
723
|
-
},
|
|
724
1195
|
host: {
|
|
725
1196
|
type: "string",
|
|
726
1197
|
description: "The hostname or IP address of the server. This can be a domain name (e.g., `example.com`) or an IP address (e.g., `192.168.1.1`)."
|
|
727
1198
|
},
|
|
1199
|
+
protocol: {
|
|
1200
|
+
type: "string",
|
|
1201
|
+
enum: ["http", "https"],
|
|
1202
|
+
description: 'The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n* @defaultValue "http" for local development, "https" for otherwise'
|
|
1203
|
+
},
|
|
728
1204
|
port: {
|
|
729
1205
|
type: "number",
|
|
730
|
-
description: "The port number to be used for the connection. Common values include `80` for HTTP and `443` for HTTPS
|
|
1206
|
+
description: "The port number to be used for the connection. Common values include `80` for HTTP and `443` for HTTPS."
|
|
731
1207
|
}
|
|
732
|
-
}
|
|
733
|
-
required: ["host"]
|
|
1208
|
+
}
|
|
734
1209
|
},
|
|
735
|
-
|
|
1210
|
+
HostConfig: {
|
|
736
1211
|
type: "object",
|
|
737
1212
|
properties: {
|
|
738
|
-
|
|
739
|
-
type: "string",
|
|
740
|
-
description: "Vercel project ID"
|
|
741
|
-
},
|
|
742
|
-
projectName: {
|
|
1213
|
+
protocol: {
|
|
743
1214
|
type: "string",
|
|
744
|
-
|
|
1215
|
+
enum: ["http", "https"],
|
|
1216
|
+
description: 'The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n* @defaultValue "http" for local development, "https" for otherwise'
|
|
745
1217
|
},
|
|
746
|
-
|
|
1218
|
+
host: {
|
|
747
1219
|
type: "string",
|
|
748
|
-
description: "The
|
|
1220
|
+
description: "The hostname or IP address of the server. This can be a domain name (e.g., `example.com`) or an IP address (e.g., `192.168.1.1`)."
|
|
749
1221
|
},
|
|
750
|
-
|
|
751
|
-
type: "
|
|
752
|
-
description: "
|
|
1222
|
+
port: {
|
|
1223
|
+
type: "number",
|
|
1224
|
+
description: "The port number to be used for the connection. Common values include `80` for HTTP and `443` for HTTPS."
|
|
753
1225
|
}
|
|
754
1226
|
},
|
|
755
|
-
required: ["
|
|
1227
|
+
required: ["host"],
|
|
1228
|
+
additionalProperties: false
|
|
756
1229
|
},
|
|
757
|
-
|
|
1230
|
+
ChildApplication: {
|
|
758
1231
|
type: "object",
|
|
759
1232
|
properties: {
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
const: false,
|
|
763
|
-
description: "The default application is used no other application is matched via the routing config"
|
|
764
|
-
},
|
|
765
|
-
routing: {
|
|
766
|
-
$ref: "#/definitions/Routing"
|
|
1233
|
+
vercel: {
|
|
1234
|
+
$ref: "#/definitions/Vercel"
|
|
767
1235
|
},
|
|
768
1236
|
development: {
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
fallback: {
|
|
775
|
-
$ref: "#/definitions/HostConfig",
|
|
776
|
-
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."
|
|
777
|
-
},
|
|
778
|
-
task: {
|
|
779
|
-
type: "string",
|
|
780
|
-
description: "Optional task to run when starting the development server. Should reference a script in the package.json of the application."
|
|
781
|
-
}
|
|
782
|
-
},
|
|
783
|
-
required: ["local"]
|
|
1237
|
+
$ref: "#/definitions/Development"
|
|
1238
|
+
},
|
|
1239
|
+
routing: {
|
|
1240
|
+
$ref: "#/definitions/Routing",
|
|
1241
|
+
description: "Groups of path expressions that are routed to this application."
|
|
784
1242
|
},
|
|
785
1243
|
production: {
|
|
786
1244
|
$ref: "#/definitions/HostConfig"
|
|
787
|
-
},
|
|
788
|
-
metadata: {
|
|
789
|
-
type: "object",
|
|
790
|
-
additionalProperties: {
|
|
791
|
-
type: "string"
|
|
792
|
-
}
|
|
793
|
-
},
|
|
794
|
-
federation: {
|
|
795
|
-
type: "object",
|
|
796
|
-
properties: {
|
|
797
|
-
exposes: {
|
|
798
|
-
type: "array",
|
|
799
|
-
items: {
|
|
800
|
-
type: "object",
|
|
801
|
-
properties: {
|
|
802
|
-
name: {
|
|
803
|
-
type: "string",
|
|
804
|
-
description: "The name of the module - should be used when importing the module from another application"
|
|
805
|
-
},
|
|
806
|
-
path: {
|
|
807
|
-
type: "string",
|
|
808
|
-
description: "Relative path to the module within its `application`"
|
|
809
|
-
}
|
|
810
|
-
},
|
|
811
|
-
required: ["name", "path"]
|
|
812
|
-
},
|
|
813
|
-
description: "Modules that are exposed by this application"
|
|
814
|
-
},
|
|
815
|
-
uses: {
|
|
816
|
-
type: "array",
|
|
817
|
-
items: {
|
|
818
|
-
type: "string"
|
|
819
|
-
},
|
|
820
|
-
description: "Modules that are used by this application. Only the name of the module is required."
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
},
|
|
824
|
-
vercel: {
|
|
825
|
-
$ref: "#/definitions/Vercel"
|
|
826
1245
|
}
|
|
827
1246
|
},
|
|
828
|
-
required: ["
|
|
1247
|
+
required: ["routing"],
|
|
1248
|
+
additionalProperties: false
|
|
829
1249
|
},
|
|
830
|
-
|
|
831
|
-
type: "
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
$ref: "#/definitions/VercelOptions",
|
|
835
|
-
description: "Micro-Frontends wide options for Vercel."
|
|
836
|
-
},
|
|
837
|
-
localProxy: {
|
|
838
|
-
$ref: "#/definitions/LocalProxyOptions",
|
|
839
|
-
description: "Options for local proxy."
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
},
|
|
843
|
-
VercelOptions: {
|
|
844
|
-
type: "object",
|
|
845
|
-
properties: {
|
|
846
|
-
previewDeploymentSuffix: {
|
|
847
|
-
type: "string",
|
|
848
|
-
description: "If your team uses a custom Preview Deployment Suffix, please specify it here. See https://vercel.com/docs/deployments/preview-deployment-suffix. The default is `vercel.app`."
|
|
849
|
-
},
|
|
850
|
-
teamSlug: {
|
|
851
|
-
type: "string",
|
|
852
|
-
description: "Team slug for the Vercel team"
|
|
853
|
-
},
|
|
854
|
-
disableOverrides: {
|
|
855
|
-
type: "boolean",
|
|
856
|
-
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."
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
},
|
|
860
|
-
LocalProxyOptions: {
|
|
861
|
-
type: "object",
|
|
862
|
-
properties: {
|
|
863
|
-
port: {
|
|
864
|
-
type: "number",
|
|
865
|
-
description: "The port number used by the local proxy server.\n\nThe default is `3024`."
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
};
|
|
871
|
-
|
|
872
|
-
// src/config/utils/load-schema.ts
|
|
873
|
-
var SCHEMA = schema_default;
|
|
874
|
-
|
|
875
|
-
// src/config/validation.ts
|
|
876
|
-
var validateSchema = (configString) => {
|
|
877
|
-
const parsedConfig = (0, import_jsonc_parser.parse)(configString);
|
|
878
|
-
const ajv = new import_ajv.Ajv();
|
|
879
|
-
const validate = ajv.compile(SCHEMA);
|
|
880
|
-
const isValid = validate(parsedConfig);
|
|
881
|
-
if (!isValid) {
|
|
882
|
-
throw new MicrofrontendError(
|
|
883
|
-
`Invalid config: ${ajv.errorsText(validate.errors)}`,
|
|
884
|
-
{ type: "config", subtype: "does_not_match_schema" }
|
|
885
|
-
);
|
|
886
|
-
}
|
|
887
|
-
return parsedConfig;
|
|
888
|
-
};
|
|
889
|
-
var SUPPORTED_VERSIONS2 = ["1"];
|
|
890
|
-
var validateVersion = (version) => {
|
|
891
|
-
if (!SUPPORTED_VERSIONS2.includes(version)) {
|
|
892
|
-
throw new MicrofrontendError(
|
|
893
|
-
`Unsupported version: ${version}. Supported versions are: ${SUPPORTED_VERSIONS2.join(
|
|
894
|
-
", "
|
|
895
|
-
)}`,
|
|
896
|
-
{ type: "config", subtype: "unsupported_version" }
|
|
897
|
-
);
|
|
898
|
-
}
|
|
899
|
-
};
|
|
900
|
-
function validateMainPath(applicationConfigsById) {
|
|
901
|
-
for (const [id, app] of Object.entries(applicationConfigsById)) {
|
|
902
|
-
const { defaultRoute } = app.vercel ?? {};
|
|
903
|
-
if (!defaultRoute) {
|
|
904
|
-
continue;
|
|
905
|
-
}
|
|
906
|
-
if (isDefaultApplicationConfig(app)) {
|
|
907
|
-
const pathsWithApp = [];
|
|
908
|
-
for (const [otherId, otherApp] of Object.entries(
|
|
909
|
-
applicationConfigsById
|
|
910
|
-
)) {
|
|
911
|
-
if (isDefaultApplicationConfig(otherApp)) {
|
|
912
|
-
continue;
|
|
913
|
-
}
|
|
914
|
-
pathsWithApp.push({
|
|
915
|
-
id: otherId,
|
|
916
|
-
paths: otherApp.routing.matches.flatMap((match) => match.paths)
|
|
917
|
-
});
|
|
918
|
-
}
|
|
919
|
-
for (const { id: otherId, paths } of pathsWithApp) {
|
|
920
|
-
const isValid = paths.every((path3) => {
|
|
921
|
-
const matcher = (0, import_path_to_regexp.pathToRegexp)(path3);
|
|
922
|
-
return !matcher.test(defaultRoute);
|
|
923
|
-
});
|
|
924
|
-
if (!isValid) {
|
|
925
|
-
throw new MicrofrontendError(
|
|
926
|
-
`default route "${defaultRoute}" cannot be used for "${id}" because it is matched by "${otherId}"`,
|
|
927
|
-
{ type: "config", subtype: "invalid_main_path" }
|
|
928
|
-
);
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
} else {
|
|
932
|
-
const allPaths = app.routing.matches.flatMap((match) => match.paths);
|
|
933
|
-
const isValid = allPaths.some((path3) => {
|
|
934
|
-
const matcher = (0, import_path_to_regexp.pathToRegexp)(path3);
|
|
935
|
-
return matcher.test(defaultRoute);
|
|
936
|
-
});
|
|
937
|
-
if (!isValid) {
|
|
938
|
-
throw new MicrofrontendError(
|
|
939
|
-
`default route "${defaultRoute}" is not included by the routing config for application "${id}"`,
|
|
940
|
-
{ type: "config", subtype: "invalid_main_path" }
|
|
941
|
-
);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
var validatePaths = (applicationConfigsById) => {
|
|
947
|
-
const pathsByApplicationId = /* @__PURE__ */ new Map();
|
|
948
|
-
const errors = [];
|
|
949
|
-
for (const [id, app] of Object.entries(applicationConfigsById)) {
|
|
950
|
-
if (isDefaultApplicationConfig(app)) {
|
|
951
|
-
continue;
|
|
952
|
-
}
|
|
953
|
-
for (const pathMatch of app.routing.matches) {
|
|
954
|
-
for (const path3 of pathMatch.paths) {
|
|
955
|
-
const maybeError = validatePathExpression(path3);
|
|
956
|
-
if (maybeError) {
|
|
957
|
-
errors.push(maybeError);
|
|
958
|
-
}
|
|
959
|
-
const existing = pathsByApplicationId.get(path3);
|
|
960
|
-
if (existing) {
|
|
961
|
-
existing.applications.push(id);
|
|
962
|
-
} else {
|
|
963
|
-
pathsByApplicationId.set(path3, {
|
|
964
|
-
applications: [id],
|
|
965
|
-
matcher: (0, import_path_to_regexp.pathToRegexp)(path3),
|
|
966
|
-
applicationId: id
|
|
967
|
-
});
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
const entries = Array.from(pathsByApplicationId.entries());
|
|
973
|
-
entries.forEach(([path3, { applications: ids, matcher, applicationId }]) => {
|
|
974
|
-
if (ids.length > 1) {
|
|
975
|
-
errors.push(
|
|
976
|
-
`Duplicate path "${path3}" for applications "${ids.join(", ")}"`
|
|
977
|
-
);
|
|
978
|
-
}
|
|
979
|
-
entries.forEach(
|
|
980
|
-
([
|
|
981
|
-
matchPath,
|
|
982
|
-
{ applications: matchIds, applicationId: matchApplicationId }
|
|
983
|
-
]) => {
|
|
984
|
-
if (path3 === matchPath) {
|
|
985
|
-
return;
|
|
986
|
-
}
|
|
987
|
-
if (applicationId === matchApplicationId) {
|
|
988
|
-
return;
|
|
989
|
-
}
|
|
990
|
-
if (matcher.test(matchPath)) {
|
|
991
|
-
const source = `"${path3}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
992
|
-
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
993
|
-
errors.push(
|
|
994
|
-
`Overlapping path detected between ${source} and ${destination}`
|
|
995
|
-
);
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
);
|
|
999
|
-
});
|
|
1000
|
-
if (errors.length) {
|
|
1001
|
-
throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
|
|
1002
|
-
type: "config",
|
|
1003
|
-
subtype: "conflicting_paths"
|
|
1004
|
-
});
|
|
1005
|
-
}
|
|
1006
|
-
};
|
|
1007
|
-
var PATH_DEFAULT_PATTERN = "[^\\/#\\?]+?";
|
|
1008
|
-
function validatePathExpression(path3) {
|
|
1009
|
-
const tokens = (0, import_path_to_regexp.parse)(path3);
|
|
1010
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
1011
|
-
const token = tokens[i];
|
|
1012
|
-
if (token === void 0) {
|
|
1013
|
-
return `token ${i} in ${path3} is undefined, this shouldn't happen`;
|
|
1014
|
-
}
|
|
1015
|
-
if (typeof token !== "string") {
|
|
1016
|
-
if (token.pattern !== PATH_DEFAULT_PATTERN) {
|
|
1017
|
-
return `Path ${path3} cannot use a regular expression wildcard`;
|
|
1018
|
-
}
|
|
1019
|
-
if (token.prefix !== "/") {
|
|
1020
|
-
return `Wildcard :${token.name} must be immediately after a / in ${path3}`;
|
|
1021
|
-
}
|
|
1022
|
-
if (token.suffix) {
|
|
1023
|
-
return `Wildcard suffix on :${token.name} is not allowed. Suffixes are not supported`;
|
|
1250
|
+
Routing: {
|
|
1251
|
+
type: "array",
|
|
1252
|
+
items: {
|
|
1253
|
+
$ref: "#/definitions/PathGroup"
|
|
1024
1254
|
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1255
|
+
},
|
|
1256
|
+
PathGroup: {
|
|
1257
|
+
type: "object",
|
|
1258
|
+
properties: {
|
|
1259
|
+
group: {
|
|
1260
|
+
type: "string",
|
|
1261
|
+
description: "Optional group name for the paths"
|
|
1262
|
+
},
|
|
1263
|
+
flag: {
|
|
1264
|
+
type: "string",
|
|
1265
|
+
description: "flag name that can be used to enable/disable all paths in the group"
|
|
1266
|
+
},
|
|
1267
|
+
paths: {
|
|
1268
|
+
type: "array",
|
|
1269
|
+
items: {
|
|
1270
|
+
type: "string"
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
},
|
|
1274
|
+
required: ["paths"],
|
|
1275
|
+
additionalProperties: false
|
|
1276
|
+
},
|
|
1277
|
+
ApplicationRouting: {
|
|
1278
|
+
type: "object",
|
|
1279
|
+
additionalProperties: {
|
|
1280
|
+
$ref: "#/definitions/Application"
|
|
1027
1281
|
}
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
);
|
|
1282
|
+
},
|
|
1283
|
+
ChildConfig: {
|
|
1284
|
+
type: "object",
|
|
1285
|
+
properties: {
|
|
1286
|
+
$schema: {
|
|
1287
|
+
type: "string"
|
|
1288
|
+
},
|
|
1289
|
+
version: {
|
|
1290
|
+
type: "string",
|
|
1291
|
+
const: "2"
|
|
1292
|
+
},
|
|
1293
|
+
options: {
|
|
1294
|
+
$ref: "#/definitions/Options"
|
|
1295
|
+
},
|
|
1296
|
+
remotes: {
|
|
1297
|
+
type: "object",
|
|
1298
|
+
additionalProperties: {
|
|
1299
|
+
$ref: "#/definitions/Application"
|
|
1300
|
+
},
|
|
1301
|
+
description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
|
|
1302
|
+
},
|
|
1303
|
+
partOf: {
|
|
1304
|
+
type: "string",
|
|
1305
|
+
description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
|
|
1306
|
+
}
|
|
1307
|
+
},
|
|
1308
|
+
required: ["partOf", "version"],
|
|
1309
|
+
additionalProperties: false
|
|
1057
1310
|
}
|
|
1058
1311
|
}
|
|
1059
1312
|
};
|
|
1060
1313
|
|
|
1061
|
-
// src/config/utils/
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
development: application.development,
|
|
1076
|
-
vercel: application.vercel
|
|
1077
|
-
};
|
|
1078
|
-
if (application.default) {
|
|
1079
|
-
return common;
|
|
1314
|
+
// src/config/schema/utils/load.ts
|
|
1315
|
+
var SCHEMA = schema_default;
|
|
1316
|
+
|
|
1317
|
+
// src/config/microfrontends/server/validation.ts
|
|
1318
|
+
function validateSchema(configString) {
|
|
1319
|
+
const parsedConfig = (0, import_jsonc_parser3.parse)(configString);
|
|
1320
|
+
const ajv = new import_ajv.Ajv();
|
|
1321
|
+
const validate = ajv.compile(SCHEMA);
|
|
1322
|
+
const isValid = validate(parsedConfig);
|
|
1323
|
+
if (!isValid) {
|
|
1324
|
+
throw new MicrofrontendError(
|
|
1325
|
+
`Invalid config: ${ajv.errorsText(validate.errors)}`,
|
|
1326
|
+
{ type: "config", subtype: "does_not_match_schema" }
|
|
1327
|
+
);
|
|
1080
1328
|
}
|
|
1081
|
-
return
|
|
1082
|
-
...common,
|
|
1083
|
-
routing: convertV1RoutingToV2Routing(application.routing)
|
|
1084
|
-
};
|
|
1329
|
+
return parsedConfig;
|
|
1085
1330
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1331
|
+
|
|
1332
|
+
// src/config/microfrontends/server/index.ts
|
|
1333
|
+
var MicrofrontendsServer = class extends Microfrontends {
|
|
1334
|
+
/**
|
|
1335
|
+
* Writes the configuration to a file.
|
|
1336
|
+
*/
|
|
1337
|
+
writeConfig(opts = {
|
|
1338
|
+
pretty: true
|
|
1339
|
+
}) {
|
|
1340
|
+
const outputPath = getOutputFilePath();
|
|
1341
|
+
import_node_fs7.default.mkdirSync((0, import_node_path8.dirname)(outputPath), { recursive: true });
|
|
1342
|
+
import_node_fs7.default.writeFileSync(
|
|
1343
|
+
outputPath,
|
|
1344
|
+
JSON.stringify(
|
|
1345
|
+
this.config.toSchemaJson(),
|
|
1346
|
+
null,
|
|
1347
|
+
opts.pretty ?? true ? 2 : void 0
|
|
1102
1348
|
)
|
|
1103
|
-
|
|
1104
|
-
}
|
|
1105
|
-
const defaultApplication = Object.entries(config.applications).find(
|
|
1106
|
-
([, application]) => application.default
|
|
1107
|
-
);
|
|
1108
|
-
if (!defaultApplication) {
|
|
1109
|
-
throw new Error("No default application found in the config");
|
|
1349
|
+
);
|
|
1110
1350
|
}
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1351
|
+
// --------- Static Methods ---------
|
|
1352
|
+
/**
|
|
1353
|
+
* Generates a MicrofrontendsServer instance from an unknown object.
|
|
1354
|
+
*/
|
|
1355
|
+
static fromUnknown({
|
|
1356
|
+
config,
|
|
1357
|
+
cookies,
|
|
1358
|
+
meta
|
|
1359
|
+
}) {
|
|
1360
|
+
const overrides = cookies ? parseOverrides(cookies) : void 0;
|
|
1361
|
+
if (typeof config === "string") {
|
|
1362
|
+
return new MicrofrontendsServer({
|
|
1363
|
+
config: MicrofrontendsServer.validate(config),
|
|
1364
|
+
overrides,
|
|
1365
|
+
meta
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1368
|
+
if (typeof config === "object") {
|
|
1369
|
+
return new MicrofrontendsServer({
|
|
1370
|
+
config,
|
|
1371
|
+
overrides,
|
|
1372
|
+
meta
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
throw new MicrofrontendError(
|
|
1376
|
+
"Invalid config: must be a string or an object",
|
|
1377
|
+
{ type: "config", subtype: "does_not_match_schema" }
|
|
1378
|
+
);
|
|
1138
1379
|
}
|
|
1380
|
+
/**
|
|
1381
|
+
* Generates a MicrofrontendsServer instance from the environment.
|
|
1382
|
+
* Uses additional validation that is only available when in a node runtime
|
|
1383
|
+
*/
|
|
1139
1384
|
static fromEnv({
|
|
1140
|
-
cookies
|
|
1385
|
+
cookies,
|
|
1386
|
+
meta
|
|
1141
1387
|
}) {
|
|
1142
|
-
return new
|
|
1143
|
-
config:
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
overrides: Overrides.parseOverrides(cookies)
|
|
1388
|
+
return new MicrofrontendsServer({
|
|
1389
|
+
config: MicrofrontendsServer.validate(getConfigStringFromEnv()),
|
|
1390
|
+
overrides: parseOverrides(cookies),
|
|
1391
|
+
meta
|
|
1147
1392
|
});
|
|
1148
1393
|
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Validates the configuration against the JSON schema
|
|
1396
|
+
*/
|
|
1397
|
+
static validate(config) {
|
|
1398
|
+
if (typeof config === "string") {
|
|
1399
|
+
const c = validateSchema(config);
|
|
1400
|
+
return c;
|
|
1401
|
+
}
|
|
1402
|
+
return config;
|
|
1403
|
+
}
|
|
1404
|
+
/**
|
|
1405
|
+
* Looks up the configuration by inferring the package root and looking for a microfrontends config file. If a file is not found,
|
|
1406
|
+
* it will look for a package in the repository with a microfrontends file that contains the current application
|
|
1407
|
+
* and use that configuration.
|
|
1408
|
+
*
|
|
1409
|
+
* This can return either a Child or Main configuration.
|
|
1410
|
+
*/
|
|
1411
|
+
static infer({
|
|
1412
|
+
directory,
|
|
1413
|
+
filePath,
|
|
1414
|
+
meta,
|
|
1415
|
+
cookies,
|
|
1416
|
+
options
|
|
1417
|
+
} = {}) {
|
|
1418
|
+
if (filePath && meta) {
|
|
1419
|
+
return MicrofrontendsServer.fromFile({
|
|
1420
|
+
filePath,
|
|
1421
|
+
cookies,
|
|
1422
|
+
meta,
|
|
1423
|
+
options
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
try {
|
|
1427
|
+
const packageRoot = findPackageRoot(directory);
|
|
1428
|
+
const packageJsonPath = (0, import_node_path8.join)(packageRoot, "package.json");
|
|
1429
|
+
const packageJson = JSON.parse(
|
|
1430
|
+
import_node_fs7.default.readFileSync(packageJsonPath, "utf-8")
|
|
1431
|
+
);
|
|
1432
|
+
if (!packageJson.name) {
|
|
1433
|
+
throw new Error(`No name found in package.json at ${packageJsonPath}`);
|
|
1434
|
+
}
|
|
1435
|
+
const configMeta = meta ?? { fromApp: packageJson.name };
|
|
1436
|
+
const maybeConfig = findConfig({ dir: packageRoot });
|
|
1437
|
+
if (maybeConfig) {
|
|
1438
|
+
return MicrofrontendsServer.fromFile({
|
|
1439
|
+
filePath: maybeConfig,
|
|
1440
|
+
cookies,
|
|
1441
|
+
meta: configMeta,
|
|
1442
|
+
options
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1445
|
+
const repositoryRoot = findRepositoryRoot();
|
|
1446
|
+
const isMonorepo2 = isMonorepo({ repositoryRoot });
|
|
1447
|
+
if (isMonorepo2) {
|
|
1448
|
+
const defaultPackage = findDefaultMicrofrontendsPackage({
|
|
1449
|
+
repositoryRoot,
|
|
1450
|
+
applicationName: packageJson.name
|
|
1451
|
+
});
|
|
1452
|
+
const maybeConfigFromDefault = findConfig({ dir: defaultPackage });
|
|
1453
|
+
if (maybeConfigFromDefault) {
|
|
1454
|
+
return MicrofrontendsServer.fromFile({
|
|
1455
|
+
filePath: maybeConfigFromDefault,
|
|
1456
|
+
cookies,
|
|
1457
|
+
meta: configMeta,
|
|
1458
|
+
options
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
throw new Error("Unable to infer");
|
|
1463
|
+
} catch (e) {
|
|
1464
|
+
throw new MicrofrontendError(
|
|
1465
|
+
"Unable to infer microfrontends configuration",
|
|
1466
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1467
|
+
);
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
/*
|
|
1471
|
+
* Generates a MicrofrontendsServer instance from a file.
|
|
1472
|
+
*/
|
|
1149
1473
|
static fromFile({
|
|
1150
|
-
filePath
|
|
1474
|
+
filePath,
|
|
1475
|
+
cookies,
|
|
1476
|
+
meta,
|
|
1477
|
+
options
|
|
1151
1478
|
}) {
|
|
1152
1479
|
try {
|
|
1153
|
-
const
|
|
1154
|
-
|
|
1155
|
-
|
|
1480
|
+
const configJson = import_node_fs7.default.readFileSync(filePath, "utf-8");
|
|
1481
|
+
const config = MicrofrontendsServer.validate(configJson);
|
|
1482
|
+
if (!isMainConfig(config) && (options == null ? void 0 : options.resolveMainConfig)) {
|
|
1483
|
+
const repositoryRoot = findRepositoryRoot();
|
|
1484
|
+
const isMonorepo2 = isMonorepo({ repositoryRoot });
|
|
1485
|
+
if (isMonorepo2) {
|
|
1486
|
+
const packagePath = findPackagePath({
|
|
1487
|
+
repositoryRoot,
|
|
1488
|
+
name: config.partOf
|
|
1489
|
+
});
|
|
1490
|
+
if (!packagePath) {
|
|
1491
|
+
throw new MicrofrontendError(
|
|
1492
|
+
`Could not find default application "${config.partOf}" in the repository`,
|
|
1493
|
+
{ type: "config", subtype: "not_found" }
|
|
1494
|
+
);
|
|
1495
|
+
}
|
|
1496
|
+
const maybeConfig = findConfig({ dir: packagePath });
|
|
1497
|
+
if (!maybeConfig) {
|
|
1498
|
+
throw new MicrofrontendError(
|
|
1499
|
+
`Could not find microfrontends configuration in ${packagePath}`,
|
|
1500
|
+
{ type: "config", subtype: "not_found" }
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
return MicrofrontendsServer.fromMainConfigFile({
|
|
1504
|
+
filePath: maybeConfig,
|
|
1505
|
+
overrides: cookies ? parseOverrides(cookies) : void 0
|
|
1506
|
+
});
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
return new MicrofrontendsServer({
|
|
1510
|
+
config,
|
|
1511
|
+
overrides: cookies ? parseOverrides(cookies) : void 0,
|
|
1512
|
+
meta
|
|
1156
1513
|
});
|
|
1157
1514
|
} catch (e) {
|
|
1158
1515
|
throw MicrofrontendError.handle(e, {
|
|
@@ -1160,20 +1517,41 @@ var MicrofrontendConfig = class extends MicrofrontendConfigCommon {
|
|
|
1160
1517
|
});
|
|
1161
1518
|
}
|
|
1162
1519
|
}
|
|
1163
|
-
|
|
1164
|
-
*
|
|
1520
|
+
/*
|
|
1521
|
+
* Generates a MicrofrontendMainConfig instance from a file.
|
|
1165
1522
|
*/
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1523
|
+
static fromMainConfigFile({
|
|
1524
|
+
filePath,
|
|
1525
|
+
overrides
|
|
1526
|
+
}) {
|
|
1527
|
+
try {
|
|
1528
|
+
const config = import_node_fs7.default.readFileSync(filePath, "utf-8");
|
|
1529
|
+
const validatedConfig = MicrofrontendsServer.validate(config);
|
|
1530
|
+
if (!isMainConfig(validatedConfig)) {
|
|
1531
|
+
throw new MicrofrontendError(
|
|
1532
|
+
`${filePath} is not a main microfrontend config`,
|
|
1533
|
+
{
|
|
1534
|
+
type: "config",
|
|
1535
|
+
subtype: "invalid_main_path"
|
|
1536
|
+
}
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
const [defaultApplication] = Object.entries(validatedConfig.applications).filter(([, app]) => isDefaultApp(app)).map(([name]) => name);
|
|
1540
|
+
if (!defaultApplication) {
|
|
1541
|
+
throw new MicrofrontendError(
|
|
1542
|
+
`No default application found. At least one application needs to be the default by omitting routing.`,
|
|
1543
|
+
{ type: "config", subtype: "no_default_application" }
|
|
1544
|
+
);
|
|
1545
|
+
}
|
|
1546
|
+
return new MicrofrontendsServer({
|
|
1547
|
+
config: validatedConfig,
|
|
1548
|
+
overrides,
|
|
1549
|
+
meta: { fromApp: defaultApplication }
|
|
1550
|
+
});
|
|
1551
|
+
} catch (e) {
|
|
1552
|
+
throw MicrofrontendError.handle(e, {
|
|
1553
|
+
fileName: filePath
|
|
1554
|
+
});
|
|
1177
1555
|
}
|
|
1178
1556
|
}
|
|
1179
1557
|
};
|
|
@@ -1189,19 +1567,19 @@ function displayLocalProxyInfo(port) {
|
|
|
1189
1567
|
|
|
1190
1568
|
// src/next/config/transforms/asset-prefix.ts
|
|
1191
1569
|
function transform(args) {
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
if (!((_a = zone.routing) == null ? void 0 : _a.assetPrefix)) {
|
|
1570
|
+
const { next, app } = args;
|
|
1571
|
+
if (app.isDefault()) {
|
|
1195
1572
|
return {
|
|
1196
1573
|
next
|
|
1197
1574
|
};
|
|
1198
1575
|
}
|
|
1199
|
-
if (next.assetPrefix !== void 0 && next.assetPrefix !==
|
|
1200
|
-
|
|
1201
|
-
`"assetPrefix" already set.
|
|
1576
|
+
if (next.assetPrefix !== void 0 && next.assetPrefix !== app.getAssetPrefix()) {
|
|
1577
|
+
console.log(
|
|
1578
|
+
`"assetPrefix" already set. This route must be manually configured in your microfrontend.json file.`
|
|
1202
1579
|
);
|
|
1580
|
+
} else {
|
|
1581
|
+
next.assetPrefix = `/${app.getAssetPrefix()}`;
|
|
1203
1582
|
}
|
|
1204
|
-
next.assetPrefix = `/${zone.routing.assetPrefix}`;
|
|
1205
1583
|
return {
|
|
1206
1584
|
next
|
|
1207
1585
|
};
|
|
@@ -1225,8 +1603,8 @@ function transform2(args) {
|
|
|
1225
1603
|
|
|
1226
1604
|
// src/next/config/transforms/headers.ts
|
|
1227
1605
|
function transform3(args) {
|
|
1228
|
-
const { next,
|
|
1229
|
-
if (
|
|
1606
|
+
const { next, app } = args;
|
|
1607
|
+
if (app.isDefault()) {
|
|
1230
1608
|
return {
|
|
1231
1609
|
next
|
|
1232
1610
|
};
|
|
@@ -1237,7 +1615,11 @@ function transform3(args) {
|
|
|
1237
1615
|
headers: [
|
|
1238
1616
|
{
|
|
1239
1617
|
key: "X-Vercel-Zone",
|
|
1240
|
-
value:
|
|
1618
|
+
value: app.name
|
|
1619
|
+
},
|
|
1620
|
+
{
|
|
1621
|
+
key: "X-Vercel-MFE-App",
|
|
1622
|
+
value: app.name
|
|
1241
1623
|
}
|
|
1242
1624
|
]
|
|
1243
1625
|
},
|
|
@@ -1276,82 +1658,39 @@ function transform3(args) {
|
|
|
1276
1658
|
};
|
|
1277
1659
|
}
|
|
1278
1660
|
|
|
1279
|
-
// src/routing/get-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
if (
|
|
1289
|
-
throw new Error(
|
|
1661
|
+
// src/routing/get-domain-from-environment.ts
|
|
1662
|
+
function getDomainFromEnvironment({
|
|
1663
|
+
app,
|
|
1664
|
+
target
|
|
1665
|
+
}) {
|
|
1666
|
+
var _a;
|
|
1667
|
+
const mfeProjects = JSON.parse(
|
|
1668
|
+
process.env.VERCEL_MICROFRONTENDS_PROJECTS ?? "[]"
|
|
1669
|
+
);
|
|
1670
|
+
if (mfeProjects.length === 0) {
|
|
1671
|
+
throw new Error("Missing related microfrontends project information");
|
|
1290
1672
|
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
// biome-ignore lint/style/noNonNullAssertion: Ignored using `--suppress`
|
|
1294
|
-
label: branchUrlParts[0],
|
|
1295
|
-
domain
|
|
1296
|
-
};
|
|
1297
|
-
}
|
|
1298
|
-
function getDomainSuffix(branchUrl, vercelUrl) {
|
|
1299
|
-
const branchLabelParts = parseBranchUrl(branchUrl).label.split("-");
|
|
1300
|
-
const vercelUrlLabelParts = parseBranchUrl(vercelUrl).label.split("-");
|
|
1301
|
-
const suffixParts = [];
|
|
1302
|
-
for (let i = 1; i < branchLabelParts.length; i++) {
|
|
1303
|
-
if (branchLabelParts.at(-1 * i) === vercelUrlLabelParts.at(-1 * i)) {
|
|
1304
|
-
suffixParts.push(branchLabelParts.at(-1 * i) ?? "");
|
|
1305
|
-
}
|
|
1673
|
+
if (!((_a = app.vercel) == null ? void 0 : _a.projectId)) {
|
|
1674
|
+
throw new Error(`Missing applications[${app.name}].vercel.projectId`);
|
|
1306
1675
|
}
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1676
|
+
const vercelProject = mfeProjects.find(
|
|
1677
|
+
(p) => {
|
|
1678
|
+
var _a2;
|
|
1679
|
+
return p.project.id === ((_a2 = app.vercel) == null ? void 0 : _a2.projectId);
|
|
1680
|
+
}
|
|
1681
|
+
);
|
|
1682
|
+
if (!vercelProject) {
|
|
1313
1683
|
throw new Error(
|
|
1314
|
-
`Missing
|
|
1684
|
+
`Missing related microfrontends project information for application "${app.name}"`
|
|
1315
1685
|
);
|
|
1316
1686
|
}
|
|
1317
|
-
const
|
|
1318
|
-
if (
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
const gitBranch = `git-${VERCEL_GIT_COMMIT_REF.toLocaleLowerCase()}`;
|
|
1323
|
-
const gitBranchForHash = `git-${VERCEL_GIT_COMMIT_REF}`;
|
|
1324
|
-
const urlSafeBranch = makeUrlSafe(gitBranch);
|
|
1325
|
-
const urlSafeProjectName = makeUrlSafe(targetVercelProjectName);
|
|
1326
|
-
const maxLabelLength = getMaxLabelLength(domain);
|
|
1327
|
-
const label = [urlSafeProjectName, urlSafeBranch, stagingSuffix].filter(Boolean).join("-");
|
|
1328
|
-
if (label.length > maxLabelLength) {
|
|
1329
|
-
let newLabel = makeUrlSafe(stagingSuffix).slice(0, maxLabelLength);
|
|
1330
|
-
const hash = (0, import_node_crypto.createHash)("sha256").update(`${gitBranchForHash}${targetVercelProjectName}`).digest("hex").slice(0, 6);
|
|
1331
|
-
newLabel = [hash, newLabel].filter(Boolean).join("-");
|
|
1332
|
-
const projectNamePart = makeUrlSafe(
|
|
1333
|
-
urlSafeProjectName.slice(0, maxLabelLength - newLabel.length - 1 - 4)
|
|
1334
|
-
);
|
|
1335
|
-
const branchPart = makeUrlSafe(
|
|
1336
|
-
urlSafeBranch.slice(
|
|
1337
|
-
0,
|
|
1338
|
-
Math.max(
|
|
1339
|
-
0,
|
|
1340
|
-
maxLabelLength - (newLabel.length + projectNamePart.length) - 2
|
|
1341
|
-
)
|
|
1342
|
-
)
|
|
1343
|
-
);
|
|
1344
|
-
if (branchPart.length >= 3) {
|
|
1345
|
-
newLabel = [branchPart, newLabel].filter(Boolean).join("-");
|
|
1346
|
-
}
|
|
1347
|
-
if (projectNamePart) {
|
|
1348
|
-
newLabel = [projectNamePart, newLabel].filter(Boolean).join("-");
|
|
1349
|
-
}
|
|
1350
|
-
return `https://${newLabel}.${domain}`;
|
|
1351
|
-
}
|
|
1352
|
-
return `https://${label}.${domain}`;
|
|
1687
|
+
const domain = target === "preview" && vercelProject.preview.branch ? vercelProject.preview.branch : vercelProject.production.alias ?? vercelProject.production.url;
|
|
1688
|
+
if (!domain) {
|
|
1689
|
+
throw new Error(
|
|
1690
|
+
`Missing domain for target "${target}" in application "${app.name}"`
|
|
1691
|
+
);
|
|
1353
1692
|
}
|
|
1354
|
-
return
|
|
1693
|
+
return domain.startsWith("https://") ? domain : `https://${domain}`;
|
|
1355
1694
|
}
|
|
1356
1695
|
|
|
1357
1696
|
// src/routing/get-domain-for-current-environment.ts
|
|
@@ -1367,34 +1706,45 @@ ${line}
|
|
|
1367
1706
|
`);
|
|
1368
1707
|
}
|
|
1369
1708
|
}
|
|
1370
|
-
function
|
|
1709
|
+
function getCurrentEnvironment() {
|
|
1710
|
+
const isDevelopment = !process.env.VERCEL_ENV || process.env.VERCEL_ENV === "development";
|
|
1711
|
+
const isPreview = process.env.VERCEL_ENV === "preview";
|
|
1712
|
+
const isProduction2 = process.env.VERCEL_ENV === "production";
|
|
1713
|
+
if (isDevelopment) {
|
|
1714
|
+
return { group: "development" };
|
|
1715
|
+
} else if (isProduction2) {
|
|
1716
|
+
return { group: "production" };
|
|
1717
|
+
} else if (isPreview) {
|
|
1718
|
+
return { group: "preview" };
|
|
1719
|
+
}
|
|
1720
|
+
return { group: "custom", name: process.env.VERCEL_ENV };
|
|
1721
|
+
}
|
|
1722
|
+
function getDomainForCurrentEnvironment(config, appName, opts = {}) {
|
|
1371
1723
|
var _a;
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
return domain;
|
|
1384
|
-
} else if (process.env.VERCEL_ENV === "preview") {
|
|
1385
|
-
const MFE_PREVIEW_DOMAINS = JSON.parse(
|
|
1386
|
-
process.env.MFE_PREVIEW_DOMAINS ?? "{}"
|
|
1387
|
-
);
|
|
1388
|
-
if (MFE_PREVIEW_DOMAINS[zoneName]) {
|
|
1389
|
-
debugDomains(zoneName, "preview", MFE_PREVIEW_DOMAINS[zoneName]);
|
|
1390
|
-
return MFE_PREVIEW_DOMAINS[zoneName];
|
|
1724
|
+
const app = config.getApplication(appName);
|
|
1725
|
+
if (!opts.ignoreOverride && ((_a = app.overrides) == null ? void 0 : _a.environment)) {
|
|
1726
|
+
return app.overrides.environment.toString();
|
|
1727
|
+
}
|
|
1728
|
+
const { group } = getCurrentEnvironment();
|
|
1729
|
+
const productionHost = config.getDefaultApplication().production.toString();
|
|
1730
|
+
switch (group) {
|
|
1731
|
+
case "development": {
|
|
1732
|
+
const domain = ["test", "development"].includes(process.env.NODE_ENV) ? app.development.local.toString() : productionHost;
|
|
1733
|
+
debugDomains(appName, "development", domain);
|
|
1734
|
+
return domain;
|
|
1391
1735
|
}
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1736
|
+
case "preview": {
|
|
1737
|
+
return getDomainFromEnvironment({ app, target: "preview" });
|
|
1738
|
+
}
|
|
1739
|
+
case "production": {
|
|
1740
|
+
return getDomainFromEnvironment({ app, target: "production" });
|
|
1741
|
+
}
|
|
1742
|
+
case "custom":
|
|
1743
|
+
console.warn(
|
|
1744
|
+
`Custom environments are not supported in getDomainForCurrentEnvironment`
|
|
1745
|
+
);
|
|
1746
|
+
return productionHost;
|
|
1395
1747
|
}
|
|
1396
|
-
debugDomains(zoneName, process.env.VERCEL_ENV, zone.production.toString());
|
|
1397
|
-
return zone.production.toString();
|
|
1398
1748
|
}
|
|
1399
1749
|
|
|
1400
1750
|
// src/next/config/transforms/rewrites.ts
|
|
@@ -1416,11 +1766,11 @@ ${table}
|
|
|
1416
1766
|
`);
|
|
1417
1767
|
}
|
|
1418
1768
|
}
|
|
1419
|
-
function pathToRewrites(
|
|
1769
|
+
function pathToRewrites(path5) {
|
|
1420
1770
|
var _a;
|
|
1421
1771
|
const regex = /(?<base>^.+)\/:.+\*$/;
|
|
1422
|
-
const match = regex.exec(
|
|
1423
|
-
const paths = [
|
|
1772
|
+
const match = regex.exec(path5);
|
|
1773
|
+
const paths = [path5];
|
|
1424
1774
|
if ((_a = match == null ? void 0 : match.groups) == null ? void 0 : _a.base) {
|
|
1425
1775
|
paths.unshift(match.groups.base);
|
|
1426
1776
|
}
|
|
@@ -1449,42 +1799,39 @@ function rewritesMapToArr(rewrites) {
|
|
|
1449
1799
|
});
|
|
1450
1800
|
}
|
|
1451
1801
|
function transform4(args) {
|
|
1452
|
-
const { next, microfrontend,
|
|
1802
|
+
const { next, microfrontend, app } = args;
|
|
1453
1803
|
const buildBeforeFiles = () => {
|
|
1454
|
-
var _a, _b, _c, _d;
|
|
1455
1804
|
const rewrites = /* @__PURE__ */ new Map();
|
|
1456
|
-
if ((
|
|
1457
|
-
rewrites.set(`/${
|
|
1805
|
+
if (!app.isDefault()) {
|
|
1806
|
+
rewrites.set(`/${app.getAssetPrefix()}/_next/:path+`, {
|
|
1458
1807
|
destination: {
|
|
1459
1808
|
pathname: `/_next/:path+`
|
|
1460
1809
|
}
|
|
1461
1810
|
});
|
|
1462
|
-
|
|
1463
|
-
|
|
1811
|
+
rewrites.set(`/${app.getAssetPrefix()}/.well-known/vercel/flags`, {
|
|
1812
|
+
destination: {
|
|
1813
|
+
pathname: `/.well-known/vercel/flags`
|
|
1814
|
+
}
|
|
1815
|
+
});
|
|
1816
|
+
if (process.env.VERCEL_MICROFRONTENDS_CONSOLIDATE_SPEED_INSIGHTS === "1") {
|
|
1817
|
+
rewrites.set(`/${app.getAssetPrefix()}/_vercel/:path*`, {
|
|
1464
1818
|
destination: { pathname: "/_vercel/:path*" }
|
|
1465
1819
|
});
|
|
1466
1820
|
}
|
|
1467
|
-
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
domain,
|
|
1482
|
-
pathname: `/${z.routing.assetPrefix}/:path+`
|
|
1483
|
-
}
|
|
1484
|
-
});
|
|
1485
|
-
}
|
|
1486
|
-
for (const group of routing.matches) {
|
|
1487
|
-
if ((_d = group.options) == null ? void 0 : _d.flag) {
|
|
1821
|
+
} else if (microfrontend instanceof MicrofrontendMainConfig) {
|
|
1822
|
+
for (const [_, a] of Object.entries(
|
|
1823
|
+
microfrontend.getChildApplications()
|
|
1824
|
+
)) {
|
|
1825
|
+
const { routing } = a;
|
|
1826
|
+
const domain = getDomainForCurrentEnvironment(microfrontend, a.name);
|
|
1827
|
+
rewrites.set(`/${a.getAssetPrefix()}/:path+`, {
|
|
1828
|
+
destination: {
|
|
1829
|
+
domain,
|
|
1830
|
+
pathname: `/${a.getAssetPrefix()}/:path+`
|
|
1831
|
+
}
|
|
1832
|
+
});
|
|
1833
|
+
for (const group of routing) {
|
|
1834
|
+
if (group.flag) {
|
|
1488
1835
|
continue;
|
|
1489
1836
|
} else {
|
|
1490
1837
|
for (const source of group.paths) {
|
|
@@ -1498,7 +1845,6 @@ function transform4(args) {
|
|
|
1498
1845
|
}
|
|
1499
1846
|
}
|
|
1500
1847
|
}
|
|
1501
|
-
} else {
|
|
1502
1848
|
}
|
|
1503
1849
|
return rewritesMapToArr(rewrites);
|
|
1504
1850
|
};
|
|
@@ -1535,17 +1881,44 @@ function transform4(args) {
|
|
|
1535
1881
|
}
|
|
1536
1882
|
|
|
1537
1883
|
// src/next/config/transforms/server-actions.ts
|
|
1884
|
+
function debugRewrites2(allowedOrigins) {
|
|
1885
|
+
if (process.env.MFE_DEBUG === "true" && allowedOrigins) {
|
|
1886
|
+
const indent = " ".repeat(4);
|
|
1887
|
+
const header = "server actions allowed origins";
|
|
1888
|
+
const separator = "\u23AF".repeat(header.length);
|
|
1889
|
+
const maxSourceLength = Math.max(
|
|
1890
|
+
...allowedOrigins.map((key) => key.length)
|
|
1891
|
+
);
|
|
1892
|
+
const table = allowedOrigins.map((origin, idx) => {
|
|
1893
|
+
const paddedSource = origin.padEnd(maxSourceLength);
|
|
1894
|
+
return `${indent} ${idx + 1}. ${paddedSource}`;
|
|
1895
|
+
}).join("\n");
|
|
1896
|
+
console.log(`${indent}${header}
|
|
1897
|
+
${indent}${separator}
|
|
1898
|
+
${table}
|
|
1899
|
+
`);
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1538
1902
|
var formatDomainForServerAction = (domain) => domain.replace(/https?:\/\//, "");
|
|
1539
1903
|
function transform5(args) {
|
|
1540
|
-
var _a;
|
|
1541
|
-
const { next,
|
|
1542
|
-
|
|
1904
|
+
var _a, _b;
|
|
1905
|
+
const { next, app, microfrontend } = args;
|
|
1906
|
+
if (microfrontend instanceof MicrofrontendChildConfig) {
|
|
1907
|
+
console.warn(
|
|
1908
|
+
"server actions transform requires the full config - skipping"
|
|
1909
|
+
);
|
|
1910
|
+
return {
|
|
1911
|
+
next
|
|
1912
|
+
};
|
|
1913
|
+
}
|
|
1914
|
+
const defaultApplication = microfrontend.getDefaultApplication();
|
|
1915
|
+
const appsToAllow = [
|
|
1543
1916
|
// this zone - this is included by default unless allowedOrigins is overridden (which we are)
|
|
1544
1917
|
// so we re-add it here.
|
|
1545
|
-
|
|
1918
|
+
app,
|
|
1546
1919
|
// this is the default zone for the microfrontend. Allow child zones to call server actions
|
|
1547
1920
|
// that are in the default zone.
|
|
1548
|
-
|
|
1921
|
+
defaultApplication
|
|
1549
1922
|
];
|
|
1550
1923
|
const existingServerActionConfig = (_a = next.experimental) == null ? void 0 : _a.serverActions;
|
|
1551
1924
|
next.experimental = {
|
|
@@ -1554,15 +1927,23 @@ function transform5(args) {
|
|
|
1554
1927
|
...existingServerActionConfig,
|
|
1555
1928
|
allowedOrigins: Array.from(
|
|
1556
1929
|
/* @__PURE__ */ new Set([
|
|
1930
|
+
// existing
|
|
1557
1931
|
...(existingServerActionConfig == null ? void 0 : existingServerActionConfig.allowedOrigins) ?? [],
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1932
|
+
// this deployments host
|
|
1933
|
+
...process.env.VERCEL_URL ? [formatDomainForServerAction(process.env.VERCEL_URL)] : [],
|
|
1934
|
+
// default application host
|
|
1935
|
+
formatDomainForServerAction(defaultApplication.production.toString()),
|
|
1936
|
+
// environment specific microfrontend hosts
|
|
1937
|
+
...appsToAllow.flatMap((a) => [
|
|
1938
|
+
formatDomainForServerAction(
|
|
1939
|
+
getDomainForCurrentEnvironment(microfrontend, a.name)
|
|
1940
|
+
)
|
|
1561
1941
|
])
|
|
1562
1942
|
])
|
|
1563
1943
|
)
|
|
1564
1944
|
}
|
|
1565
1945
|
};
|
|
1946
|
+
debugRewrites2((_b = next.experimental.serverActions) == null ? void 0 : _b.allowedOrigins);
|
|
1566
1947
|
return {
|
|
1567
1948
|
next
|
|
1568
1949
|
};
|
|
@@ -1571,14 +1952,6 @@ function transform5(args) {
|
|
|
1571
1952
|
// src/next/config/transforms/webpack.ts
|
|
1572
1953
|
function transform6(args) {
|
|
1573
1954
|
const { next, microfrontend } = args;
|
|
1574
|
-
const previewDomains = process.env.VERCEL_ENV === "preview" ? microfrontend.getAllApplications().reduce(
|
|
1575
|
-
(obj, app) => {
|
|
1576
|
-
obj[app.name] = getPreviewDomain(app);
|
|
1577
|
-
return obj;
|
|
1578
|
-
},
|
|
1579
|
-
// eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter -- needed to satisfy TSC
|
|
1580
|
-
{}
|
|
1581
|
-
) : {};
|
|
1582
1955
|
const configWithWebpack = {
|
|
1583
1956
|
...next,
|
|
1584
1957
|
webpack(cfg, context) {
|
|
@@ -1587,8 +1960,7 @@ function transform6(args) {
|
|
|
1587
1960
|
if (isServer || nextRuntime === "edge") {
|
|
1588
1961
|
config.plugins.push(
|
|
1589
1962
|
new wpFromNext.EnvironmentPlugin({
|
|
1590
|
-
MFE_CONFIG: JSON.stringify(microfrontend.serialize())
|
|
1591
|
-
MFE_PREVIEW_DOMAINS: JSON.stringify(previewDomains)
|
|
1963
|
+
MFE_CONFIG: JSON.stringify(microfrontend.serialize())
|
|
1592
1964
|
})
|
|
1593
1965
|
);
|
|
1594
1966
|
}
|
|
@@ -1628,21 +2000,6 @@ var transforms = {
|
|
|
1628
2000
|
webpack: transform6
|
|
1629
2001
|
};
|
|
1630
2002
|
|
|
1631
|
-
// src/config/client/client-config.ts
|
|
1632
|
-
function getConfigForClient(config) {
|
|
1633
|
-
return {
|
|
1634
|
-
applications: Object.fromEntries(
|
|
1635
|
-
Object.entries(config.applications).map(([name, application]) => [
|
|
1636
|
-
name,
|
|
1637
|
-
{
|
|
1638
|
-
default: application.default,
|
|
1639
|
-
routing: application.routing
|
|
1640
|
-
}
|
|
1641
|
-
])
|
|
1642
|
-
)
|
|
1643
|
-
};
|
|
1644
|
-
}
|
|
1645
|
-
|
|
1646
2003
|
// src/next/config/env.ts
|
|
1647
2004
|
function debugEnv(env) {
|
|
1648
2005
|
if (process.env.MFE_DEBUG === "true") {
|
|
@@ -1661,32 +2018,18 @@ ${table}
|
|
|
1661
2018
|
}
|
|
1662
2019
|
}
|
|
1663
2020
|
function setEnvironment({
|
|
1664
|
-
|
|
1665
|
-
|
|
2021
|
+
app,
|
|
2022
|
+
microfrontends
|
|
1666
2023
|
}) {
|
|
1667
|
-
var _a, _b, _c, _d;
|
|
1668
|
-
const previewDomains = process.env.VERCEL_ENV === "preview" ? config.getAllApplications().reduce(
|
|
1669
|
-
(obj, app) => {
|
|
1670
|
-
obj[app.name] = getPreviewDomain(app);
|
|
1671
|
-
return obj;
|
|
1672
|
-
},
|
|
1673
|
-
// eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter -- needed to satisfy TSC
|
|
1674
|
-
{}
|
|
1675
|
-
) : {};
|
|
1676
2024
|
const clientEnvs = {
|
|
1677
|
-
NEXT_PUBLIC_MFE_CURRENT_APPLICATION:
|
|
2025
|
+
NEXT_PUBLIC_MFE_CURRENT_APPLICATION: app.name,
|
|
1678
2026
|
NEXT_PUBLIC_MFE_CLIENT_CONFIG: JSON.stringify(
|
|
1679
|
-
|
|
1680
|
-
)
|
|
1681
|
-
...((_a = zone.vercel) == null ? void 0 : _a.routeSpeedInsightsToDefaultZone) && ((_b = zone.routing) == null ? void 0 : _b.assetPrefix) ? {} : {
|
|
1682
|
-
NEXT_PUBLIC_SPEED_INSIGHTS_BASEPATH: (_c = zone.routing) == null ? void 0 : _c.assetPrefix,
|
|
1683
|
-
NEXT_PUBLIC_WEB_ANALYTICS_BASEPATH: (_d = zone.routing) == null ? void 0 : _d.assetPrefix
|
|
1684
|
-
}
|
|
2027
|
+
microfrontends.config.toClientConfig().serialize()
|
|
2028
|
+
)
|
|
1685
2029
|
};
|
|
1686
2030
|
const serverEnvs = {
|
|
1687
|
-
MFE_CURRENT_APPLICATION:
|
|
1688
|
-
|
|
1689
|
-
MFE_CONFIG: JSON.stringify(config.getConfig())
|
|
2031
|
+
MFE_CURRENT_APPLICATION: app.name,
|
|
2032
|
+
MFE_CONFIG: JSON.stringify(microfrontends.config.getConfig())
|
|
1690
2033
|
};
|
|
1691
2034
|
const allEnvs = { ...clientEnvs, ...serverEnvs };
|
|
1692
2035
|
for (const [key, value] of Object.entries(allEnvs)) {
|
|
@@ -1705,37 +2048,12 @@ function isProduction(opts) {
|
|
|
1705
2048
|
}
|
|
1706
2049
|
return process.env.VERCEL_ENV === "production";
|
|
1707
2050
|
}
|
|
1708
|
-
function getConfigPath(opts) {
|
|
1709
|
-
var _a;
|
|
1710
|
-
if (opts == null ? void 0 : opts.configPath) {
|
|
1711
|
-
return { configPath: opts.configPath };
|
|
1712
|
-
}
|
|
1713
|
-
try {
|
|
1714
|
-
const vercelJsonString = import_node_fs3.default.readFileSync("./vercel.json", "utf-8");
|
|
1715
|
-
const vercelJson = JSON.parse(vercelJsonString);
|
|
1716
|
-
if (!((_a = vercelJson.microFrontends) == null ? void 0 : _a.config)) {
|
|
1717
|
-
throw new MicrofrontendError(
|
|
1718
|
-
`vercel.json file missing required field "microFrontends.config"`,
|
|
1719
|
-
{
|
|
1720
|
-
type: "vercelJson",
|
|
1721
|
-
subtype: "missing_field_microFrontend_config_path",
|
|
1722
|
-
source: "@vercel/microfrontends/next"
|
|
1723
|
-
}
|
|
1724
|
-
);
|
|
1725
|
-
}
|
|
1726
|
-
return { configPath: vercelJson.microFrontends.config };
|
|
1727
|
-
} catch (err) {
|
|
1728
|
-
throw MicrofrontendError.handle(err, {
|
|
1729
|
-
fileName: "vercel.json"
|
|
1730
|
-
});
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
2051
|
function getApplicationContext(opts) {
|
|
1734
2052
|
if (opts == null ? void 0 : opts.appName) {
|
|
1735
2053
|
return { name: opts.appName };
|
|
1736
2054
|
}
|
|
1737
2055
|
try {
|
|
1738
|
-
const packageJsonString =
|
|
2056
|
+
const packageJsonString = import_node_fs8.default.readFileSync("./package.json", "utf-8");
|
|
1739
2057
|
const packageJson = JSON.parse(packageJsonString);
|
|
1740
2058
|
if (!packageJson.name) {
|
|
1741
2059
|
throw new MicrofrontendError(
|
|
@@ -1759,13 +2077,15 @@ function withMicrofrontends(nextConfig, opts) {
|
|
|
1759
2077
|
if (opts == null ? void 0 : opts.debug) {
|
|
1760
2078
|
process.env.MFE_DEBUG = "true";
|
|
1761
2079
|
}
|
|
1762
|
-
const { name } = getApplicationContext(opts);
|
|
1763
|
-
const
|
|
1764
|
-
|
|
1765
|
-
|
|
2080
|
+
const { name: fromApp } = getApplicationContext(opts);
|
|
2081
|
+
const microfrontends = MicrofrontendsServer.infer({
|
|
2082
|
+
filePath: opts == null ? void 0 : opts.configPath,
|
|
2083
|
+
meta: {
|
|
2084
|
+
fromApp
|
|
2085
|
+
}
|
|
1766
2086
|
});
|
|
1767
|
-
const
|
|
1768
|
-
setEnvironment({
|
|
2087
|
+
const app = microfrontends.config.getApplication(fromApp);
|
|
2088
|
+
setEnvironment({ app, microfrontends });
|
|
1769
2089
|
let next = { ...nextConfig };
|
|
1770
2090
|
for (const [key, transform7] of typedEntries(transforms)) {
|
|
1771
2091
|
if ((_a = opts == null ? void 0 : opts.skipTransforms) == null ? void 0 : _a.includes(key)) {
|
|
@@ -1774,9 +2094,9 @@ function withMicrofrontends(nextConfig, opts) {
|
|
|
1774
2094
|
}
|
|
1775
2095
|
try {
|
|
1776
2096
|
const transformedConfig = transform7({
|
|
1777
|
-
|
|
2097
|
+
app,
|
|
1778
2098
|
next,
|
|
1779
|
-
microfrontend:
|
|
2099
|
+
microfrontend: microfrontends.config,
|
|
1780
2100
|
opts: {
|
|
1781
2101
|
isProduction: isProduction(opts)
|
|
1782
2102
|
}
|
|
@@ -1786,9 +2106,9 @@ function withMicrofrontends(nextConfig, opts) {
|
|
|
1786
2106
|
console.error("Error transforming next config", e);
|
|
1787
2107
|
}
|
|
1788
2108
|
}
|
|
1789
|
-
displayLocalProxyInfo(
|
|
2109
|
+
displayLocalProxyInfo(microfrontends.config.getLocalProxyPort());
|
|
1790
2110
|
if (isVercel()) {
|
|
1791
|
-
|
|
2111
|
+
microfrontends.writeConfig();
|
|
1792
2112
|
}
|
|
1793
2113
|
return next;
|
|
1794
2114
|
}
|