@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/middleware.cjs
CHANGED
|
@@ -27,9 +27,9 @@ module.exports = __toCommonJS(middleware_exports);
|
|
|
27
27
|
|
|
28
28
|
// src/next/middleware/middleware.ts
|
|
29
29
|
var import_server = require("next/server");
|
|
30
|
-
var
|
|
30
|
+
var import_path_to_regexp3 = require("path-to-regexp");
|
|
31
31
|
|
|
32
|
-
// src/config/
|
|
32
|
+
// src/config/microfrontends-config/isomorphic/index.ts
|
|
33
33
|
var import_jsonc_parser = require("jsonc-parser");
|
|
34
34
|
|
|
35
35
|
// src/config/errors.ts
|
|
@@ -124,131 +124,320 @@ var MicrofrontendError = class extends Error {
|
|
|
124
124
|
}
|
|
125
125
|
};
|
|
126
126
|
|
|
127
|
-
// src/
|
|
128
|
-
function
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
127
|
+
// src/config/microfrontends-config/utils/get-config-from-env.ts
|
|
128
|
+
function getConfigStringFromEnv() {
|
|
129
|
+
const config = process.env.MFE_CONFIG;
|
|
130
|
+
if (!config) {
|
|
131
|
+
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
132
|
+
type: "config",
|
|
133
|
+
subtype: "not_found_in_env"
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return config;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/config/schema/utils/is-main-config.ts
|
|
140
|
+
function isMainConfig(c) {
|
|
141
|
+
return !("partOf" in c);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/config/schema/utils/is-default-app.ts
|
|
145
|
+
function isDefaultApp(a) {
|
|
146
|
+
return !("routing" in a);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/config/microfrontends-config/client/index.ts
|
|
150
|
+
var import_path_to_regexp = require("path-to-regexp");
|
|
151
|
+
var MicrofrontendConfigClient = class {
|
|
152
|
+
constructor(config, opts) {
|
|
153
|
+
this.pathCache = {};
|
|
154
|
+
this.serialized = config;
|
|
155
|
+
if (opts == null ? void 0 : opts.removeFlaggedPaths) {
|
|
156
|
+
for (const app of Object.values(config.applications)) {
|
|
157
|
+
if (app.routing) {
|
|
158
|
+
app.routing = app.routing.filter((match) => !match.flag);
|
|
159
|
+
}
|
|
143
160
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
161
|
+
}
|
|
162
|
+
this.applications = config.applications;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Create a new `MicrofrontendConfigClient` from a JSON string.
|
|
166
|
+
* Config must be passed in to remain framework agnostic
|
|
167
|
+
*/
|
|
168
|
+
static fromEnv(config, opts) {
|
|
169
|
+
if (!config) {
|
|
170
|
+
throw new Error("No microfrontends configuration found");
|
|
171
|
+
}
|
|
172
|
+
return new MicrofrontendConfigClient(
|
|
173
|
+
JSON.parse(config),
|
|
174
|
+
opts
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
isEqual(other) {
|
|
178
|
+
return JSON.stringify(this.applications) === JSON.stringify(other.applications);
|
|
179
|
+
}
|
|
180
|
+
getApplicationNameForPath(path) {
|
|
181
|
+
if (!path.startsWith("/")) {
|
|
182
|
+
throw new Error(`Path must start with a /`);
|
|
183
|
+
}
|
|
184
|
+
if (this.pathCache[path]) {
|
|
185
|
+
return this.pathCache[path];
|
|
186
|
+
}
|
|
187
|
+
const pathname = new URL(path, "https://example.com").pathname;
|
|
188
|
+
for (const [name, application] of Object.entries(this.applications)) {
|
|
189
|
+
if (application.routing) {
|
|
190
|
+
for (const group of application.routing) {
|
|
191
|
+
for (const childPath of group.paths) {
|
|
192
|
+
const regexp = (0, import_path_to_regexp.pathToRegexp)(childPath);
|
|
193
|
+
if (regexp.test(pathname)) {
|
|
194
|
+
this.pathCache[path] = name;
|
|
195
|
+
return name;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
150
198
|
}
|
|
151
199
|
}
|
|
152
|
-
tag = args.join(options.joinString);
|
|
153
|
-
tag = tag.replace(/\s/g, options.joinString);
|
|
154
|
-
if (options.lowercaseOnly)
|
|
155
|
-
tag = tag.toLowerCase();
|
|
156
|
-
tag = tag.replace(options.regexRemovePattern, (match) => {
|
|
157
|
-
if (match === options.joinString)
|
|
158
|
-
return match;
|
|
159
|
-
return "";
|
|
160
|
-
});
|
|
161
|
-
if (tag.length > options.maxLen)
|
|
162
|
-
tag = tag.substring(0, options.maxLen);
|
|
163
|
-
tag = tag.replace(reJoinString, options.joinString);
|
|
164
|
-
return tag;
|
|
165
200
|
}
|
|
201
|
+
const defaultApplication = Object.entries(this.applications).find(
|
|
202
|
+
([, application]) => application.default
|
|
203
|
+
);
|
|
204
|
+
if (!defaultApplication) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
this.pathCache[path] = defaultApplication[0];
|
|
208
|
+
return defaultApplication[0];
|
|
209
|
+
}
|
|
210
|
+
serialize() {
|
|
211
|
+
return this.serialized;
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// src/config/overrides/constants.ts
|
|
216
|
+
var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
|
|
217
|
+
var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
218
|
+
|
|
219
|
+
// src/config/overrides/is-override-cookie.ts
|
|
220
|
+
function isOverrideCookie(cookie) {
|
|
221
|
+
var _a;
|
|
222
|
+
return Boolean((_a = cookie.name) == null ? void 0 : _a.startsWith(OVERRIDES_COOKIE_PREFIX));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/config/overrides/get-override-from-cookie.ts
|
|
226
|
+
function getOverrideFromCookie(cookie) {
|
|
227
|
+
if (!isOverrideCookie(cookie) || !cookie.value)
|
|
228
|
+
return;
|
|
229
|
+
return {
|
|
230
|
+
application: cookie.name.replace(OVERRIDES_ENV_COOKIE_PREFIX, ""),
|
|
231
|
+
host: cookie.value
|
|
166
232
|
};
|
|
167
233
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
234
|
+
|
|
235
|
+
// src/config/overrides/parse-overrides.ts
|
|
236
|
+
function parseOverrides(cookies) {
|
|
237
|
+
const overridesConfig = { applications: {} };
|
|
238
|
+
cookies.forEach((cookie) => {
|
|
239
|
+
const override = getOverrideFromCookie(cookie);
|
|
240
|
+
if (!override)
|
|
241
|
+
return;
|
|
242
|
+
overridesConfig.applications[override.application] = {
|
|
243
|
+
environment: { host: override.host }
|
|
244
|
+
};
|
|
245
|
+
});
|
|
246
|
+
return overridesConfig;
|
|
171
247
|
}
|
|
172
248
|
|
|
173
|
-
// src/config/
|
|
174
|
-
var
|
|
175
|
-
var
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
249
|
+
// src/config/microfrontends-config/isomorphic/validation.ts
|
|
250
|
+
var import_path_to_regexp2 = require("path-to-regexp");
|
|
251
|
+
var SUPPORTED_VERSIONS = ["2"];
|
|
252
|
+
var validateConfigVersion = (version) => {
|
|
253
|
+
if (!SUPPORTED_VERSIONS.includes(version)) {
|
|
254
|
+
throw new MicrofrontendError(
|
|
255
|
+
`Unsupported version: ${version}. Supported versions are: ${SUPPORTED_VERSIONS.join(
|
|
256
|
+
", "
|
|
257
|
+
)}`,
|
|
258
|
+
{ type: "config", subtype: "unsupported_version" }
|
|
259
|
+
);
|
|
181
260
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
261
|
+
};
|
|
262
|
+
var validateConfigPaths = (applicationConfigsById) => {
|
|
263
|
+
if (!applicationConfigsById) {
|
|
264
|
+
return;
|
|
185
265
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
266
|
+
const pathsByApplicationId = /* @__PURE__ */ new Map();
|
|
267
|
+
const errors = [];
|
|
268
|
+
for (const [id, app] of Object.entries(applicationConfigsById)) {
|
|
269
|
+
if (isDefaultApp(app)) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
for (const pathMatch of app.routing) {
|
|
273
|
+
for (const path of pathMatch.paths) {
|
|
274
|
+
const maybeError = validatePathExpression(path);
|
|
275
|
+
if (maybeError) {
|
|
276
|
+
errors.push(maybeError);
|
|
277
|
+
}
|
|
278
|
+
const existing = pathsByApplicationId.get(path);
|
|
279
|
+
if (existing) {
|
|
280
|
+
existing.applications.push(id);
|
|
281
|
+
} else {
|
|
282
|
+
pathsByApplicationId.set(path, {
|
|
283
|
+
applications: [id],
|
|
284
|
+
matcher: (0, import_path_to_regexp2.pathToRegexp)(path),
|
|
285
|
+
applicationId: id
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
193
290
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
291
|
+
const entries = Array.from(pathsByApplicationId.entries());
|
|
292
|
+
entries.forEach(([path, { applications: ids, matcher, applicationId }]) => {
|
|
293
|
+
if (ids.length > 1) {
|
|
294
|
+
errors.push(
|
|
295
|
+
`Duplicate path "${path}" for applications "${ids.join(", ")}"`
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
entries.forEach(
|
|
299
|
+
([
|
|
300
|
+
matchPath,
|
|
301
|
+
{ applications: matchIds, applicationId: matchApplicationId }
|
|
302
|
+
]) => {
|
|
303
|
+
if (path === matchPath) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (applicationId === matchApplicationId) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (matcher.test(matchPath)) {
|
|
310
|
+
const source = `"${path}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
311
|
+
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
312
|
+
errors.push(
|
|
313
|
+
`Overlapping path detected between ${source} and ${destination}`
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
);
|
|
318
|
+
});
|
|
319
|
+
if (errors.length) {
|
|
320
|
+
throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
|
|
321
|
+
type: "config",
|
|
322
|
+
subtype: "conflicting_paths"
|
|
203
323
|
});
|
|
204
|
-
return overridesConfig;
|
|
205
324
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
325
|
+
};
|
|
326
|
+
var PATH_DEFAULT_PATTERN = "[^\\/#\\?]+?";
|
|
327
|
+
function validatePathExpression(path) {
|
|
328
|
+
const tokens = (0, import_path_to_regexp2.parse)(path);
|
|
329
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
330
|
+
const token = tokens[i];
|
|
331
|
+
if (token === void 0) {
|
|
332
|
+
return `token ${i} in ${path} is undefined, this shouldn't happen`;
|
|
211
333
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
334
|
+
if (typeof token !== "string") {
|
|
335
|
+
if (token.pattern !== PATH_DEFAULT_PATTERN) {
|
|
336
|
+
return `Path ${path} cannot use a regular expression wildcard`;
|
|
337
|
+
}
|
|
338
|
+
if (token.prefix !== "/") {
|
|
339
|
+
return `Wildcard :${token.name} must be immediately after a / in ${path}`;
|
|
340
|
+
}
|
|
341
|
+
if (token.suffix) {
|
|
342
|
+
return `Wildcard suffix on :${token.name} is not allowed. Suffixes are not supported`;
|
|
343
|
+
}
|
|
344
|
+
if (token.modifier && i !== tokens.length - 1) {
|
|
345
|
+
return `Modifier ${token.modifier} is not allowed on wildcard :${token.name} in ${path}. Modifiers are only allowed in the last path component`;
|
|
346
|
+
}
|
|
217
347
|
}
|
|
218
|
-
const suffix = previewDeploymentSuffix ? `.${previewDeploymentSuffix}` : `-${teamSlug}.vercel.app`;
|
|
219
|
-
return [
|
|
220
|
-
`${parsedProjectName}-git-([a-zA-Z0-9-]+)${suffix}`,
|
|
221
|
-
microfrontendConfig.getZone(zone).production.host
|
|
222
|
-
];
|
|
223
348
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
349
|
+
return void 0;
|
|
350
|
+
}
|
|
351
|
+
var validateAppPaths = (name, app) => {
|
|
352
|
+
for (const group of app.routing) {
|
|
353
|
+
for (const p of group.paths) {
|
|
354
|
+
if (p === "/") {
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (p.endsWith("/")) {
|
|
358
|
+
throw new MicrofrontendError(
|
|
359
|
+
`Invalid path for application "${name}". ${p} must not end with a slash.`,
|
|
360
|
+
{ type: "application", subtype: "invalid_path" }
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
if (!p.startsWith("/")) {
|
|
364
|
+
throw new MicrofrontendError(
|
|
365
|
+
`Invalid path for application "${name}". ${p} must start with a slash.`,
|
|
366
|
+
{ type: "application", subtype: "invalid_path" }
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
230
370
|
}
|
|
231
|
-
|
|
232
|
-
|
|
371
|
+
};
|
|
372
|
+
var validateConfigDefaultApplication = (applicationConfigsById) => {
|
|
373
|
+
if (!applicationConfigsById) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const applicationsWithRouting = Object.entries(applicationConfigsById).filter(
|
|
377
|
+
([, app]) => !isDefaultApp(app)
|
|
378
|
+
);
|
|
379
|
+
const applicationsWithRoutingNames = applicationsWithRouting.map(
|
|
380
|
+
([key]) => key
|
|
381
|
+
);
|
|
382
|
+
const numApplications = Object.keys(applicationConfigsById).length;
|
|
383
|
+
const numApplicationsWithRouting = applicationsWithRoutingNames.length;
|
|
384
|
+
const numApplicationsWithoutRouting = numApplications - numApplicationsWithRouting;
|
|
385
|
+
if (numApplicationsWithoutRouting === 0) {
|
|
386
|
+
throw new MicrofrontendError(
|
|
387
|
+
`No default application found. At least one application needs to be the default by omitting routing.`,
|
|
388
|
+
{ type: "config", subtype: "no_default_application" }
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
if (numApplicationsWithoutRouting > 1) {
|
|
392
|
+
throw new MicrofrontendError(
|
|
393
|
+
`Only one application can omit "routing". Found ${applicationsWithRoutingNames.length - Object.keys(applicationConfigsById).length > 1}.`,
|
|
394
|
+
{ type: "config", subtype: "multiple_default_applications" }
|
|
395
|
+
);
|
|
233
396
|
}
|
|
234
397
|
};
|
|
235
|
-
var Overrides = _Overrides;
|
|
236
|
-
Overrides.overrideEnvCookiePrefix = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
237
398
|
|
|
238
|
-
// src/config/
|
|
399
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
|
|
400
|
+
var PREFIX = "vc-ap";
|
|
401
|
+
function generateAssetPrefixFromName({
|
|
402
|
+
name
|
|
403
|
+
}) {
|
|
404
|
+
if (!name) {
|
|
405
|
+
throw new Error("Name is required to generate an asset prefix");
|
|
406
|
+
}
|
|
407
|
+
return `${PREFIX}-${name}`;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-port.ts
|
|
411
|
+
function generatePortFromName({
|
|
412
|
+
name,
|
|
413
|
+
minPort = 3e3,
|
|
414
|
+
maxPort = 8e3
|
|
415
|
+
}) {
|
|
416
|
+
if (!name) {
|
|
417
|
+
throw new Error("Name is required to generate a port");
|
|
418
|
+
}
|
|
419
|
+
let hash = 0;
|
|
420
|
+
for (let i = 0; i < name.length; i++) {
|
|
421
|
+
hash = (hash << 5) - hash + name.charCodeAt(i);
|
|
422
|
+
hash |= 0;
|
|
423
|
+
}
|
|
424
|
+
hash = Math.abs(hash);
|
|
425
|
+
const range = maxPort - minPort;
|
|
426
|
+
const port = minPort + hash % range;
|
|
427
|
+
return port;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// src/config/microfrontends-config/isomorphic/host.ts
|
|
239
431
|
var Host = class {
|
|
240
|
-
constructor(
|
|
241
|
-
|
|
432
|
+
constructor(hostConfig, options) {
|
|
433
|
+
const { protocol = "https", host, port } = hostConfig;
|
|
434
|
+
this.protocol = protocol;
|
|
242
435
|
this.host = host;
|
|
243
436
|
this.port = Host.getPort({ port, protocol: this.protocol });
|
|
244
|
-
this.
|
|
245
|
-
protocol,
|
|
246
|
-
host,
|
|
247
|
-
...port ? { port } : void 0
|
|
248
|
-
};
|
|
437
|
+
this.local = options == null ? void 0 : options.isLocal;
|
|
249
438
|
}
|
|
250
439
|
isLocal() {
|
|
251
|
-
return this.host === "localhost" || this.host === "127.0.0.1";
|
|
440
|
+
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
252
441
|
}
|
|
253
442
|
static getPort({
|
|
254
443
|
protocol,
|
|
@@ -274,176 +463,234 @@ var Host = class {
|
|
|
274
463
|
const url = `${this.protocol}://${this.host}${this.isDefaultPort() && !includeDefaultPort ? "" : `:${this.port}`}`;
|
|
275
464
|
return new URL(url);
|
|
276
465
|
}
|
|
277
|
-
|
|
278
|
-
|
|
466
|
+
};
|
|
467
|
+
var LocalHost = class extends Host {
|
|
468
|
+
constructor({
|
|
469
|
+
appName,
|
|
470
|
+
...hostConfig
|
|
471
|
+
}) {
|
|
472
|
+
const host = hostConfig.host ?? "localhost";
|
|
473
|
+
const port = hostConfig.port ?? generatePortFromName({ name: appName });
|
|
474
|
+
const protocol = hostConfig.protocol ?? "http";
|
|
475
|
+
super({ protocol, host, port });
|
|
279
476
|
}
|
|
280
477
|
};
|
|
281
478
|
|
|
282
|
-
// src/config/
|
|
479
|
+
// src/config/microfrontends-config/isomorphic/application.ts
|
|
283
480
|
var Application = class {
|
|
284
481
|
constructor(name, {
|
|
285
482
|
app,
|
|
286
|
-
overrides
|
|
483
|
+
overrides,
|
|
484
|
+
isDefault
|
|
287
485
|
}) {
|
|
288
|
-
|
|
486
|
+
var _a, _b;
|
|
289
487
|
this.name = name;
|
|
290
|
-
this.default = app.default;
|
|
291
|
-
this.routing = app.routing;
|
|
292
488
|
this.development = {
|
|
293
|
-
local: new
|
|
294
|
-
|
|
489
|
+
local: new LocalHost({
|
|
490
|
+
appName: name,
|
|
491
|
+
...(_a = app.development) == null ? void 0 : _a.local
|
|
492
|
+
}),
|
|
493
|
+
fallback: ((_b = app.development) == null ? void 0 : _b.fallback) ? new Host(app.development.fallback) : void 0
|
|
295
494
|
};
|
|
296
|
-
this.production = new Host(app.production);
|
|
495
|
+
this.production = app.production ? new Host(app.production) : void 0;
|
|
297
496
|
this.vercel = app.vercel;
|
|
298
497
|
this.overrides = (overrides == null ? void 0 : overrides.environment) ? {
|
|
299
498
|
environment: new Host(overrides.environment)
|
|
300
499
|
} : void 0;
|
|
500
|
+
this.default = isDefault ?? false;
|
|
501
|
+
this.serialized = app;
|
|
301
502
|
}
|
|
302
503
|
isDefault() {
|
|
303
504
|
return this.default;
|
|
304
505
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
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("/"))) {
|
|
308
|
-
throw new MicrofrontendError(
|
|
309
|
-
`Invalid assetPrefix for application "${name}". Must not start or end with a slash.`,
|
|
310
|
-
{ type: "zone", subtype: "invalid_asset_prefix" }
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
for (const group of ((_e = app.routing) == null ? void 0 : _e.matches) ?? []) {
|
|
314
|
-
for (const p of group.paths) {
|
|
315
|
-
if (p === "/") {
|
|
316
|
-
continue;
|
|
317
|
-
}
|
|
318
|
-
if (p.endsWith("/")) {
|
|
319
|
-
throw new MicrofrontendError(
|
|
320
|
-
`Invalid path for application "${name}". ${p} must not end with a slash.`,
|
|
321
|
-
{ type: "zone", subtype: "invalid_path" }
|
|
322
|
-
);
|
|
323
|
-
}
|
|
324
|
-
if (!p.startsWith("/")) {
|
|
325
|
-
throw new MicrofrontendError(
|
|
326
|
-
`Invalid path for application "${name}". ${p} must start with a slash.`,
|
|
327
|
-
{ type: "zone", subtype: "invalid_path" }
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
506
|
+
getAssetPrefix() {
|
|
507
|
+
return generateAssetPrefixFromName({ name: this.name });
|
|
332
508
|
}
|
|
333
509
|
serialize() {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
510
|
+
return this.serialized;
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
var DefaultApplication = class extends Application {
|
|
514
|
+
constructor(name, {
|
|
515
|
+
app,
|
|
516
|
+
overrides
|
|
517
|
+
}) {
|
|
518
|
+
super(name, {
|
|
519
|
+
app,
|
|
520
|
+
overrides,
|
|
521
|
+
isDefault: true
|
|
522
|
+
});
|
|
523
|
+
this.default = true;
|
|
524
|
+
this.production = new Host(app.production);
|
|
525
|
+
}
|
|
526
|
+
getAssetPrefix() {
|
|
527
|
+
return "";
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
var ChildApplication = class extends Application {
|
|
531
|
+
constructor(name, {
|
|
532
|
+
app,
|
|
533
|
+
overrides
|
|
534
|
+
}) {
|
|
535
|
+
ChildApplication.validate(name, app);
|
|
536
|
+
super(name, {
|
|
537
|
+
app,
|
|
538
|
+
overrides,
|
|
539
|
+
isDefault: false
|
|
540
|
+
});
|
|
541
|
+
this.default = false;
|
|
542
|
+
this.routing = app.routing;
|
|
543
|
+
}
|
|
544
|
+
static validate(name, app) {
|
|
545
|
+
validateAppPaths(name, app);
|
|
356
546
|
}
|
|
357
547
|
};
|
|
358
548
|
|
|
359
|
-
// src/config/
|
|
360
|
-
var SUPPORTED_VERSIONS = ["1"];
|
|
549
|
+
// src/config/microfrontends-config/isomorphic/constants.ts
|
|
361
550
|
var DEFAULT_LOCAL_PROXY_PORT = 3024;
|
|
362
|
-
|
|
551
|
+
|
|
552
|
+
// src/config/microfrontends-config/isomorphic/index.ts
|
|
553
|
+
var MicrofrontendConfigIsomorphic = class {
|
|
363
554
|
constructor({
|
|
364
555
|
config,
|
|
365
|
-
overrides
|
|
556
|
+
overrides,
|
|
557
|
+
meta
|
|
366
558
|
}) {
|
|
367
|
-
this.
|
|
368
|
-
var _a, _b, _c;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
559
|
+
this.childApplications = {};
|
|
560
|
+
var _a, _b, _c, _d;
|
|
561
|
+
MicrofrontendConfigIsomorphic.validate(config);
|
|
562
|
+
const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
563
|
+
this.overrides = overrides && !disableOverrides ? overrides : void 0;
|
|
564
|
+
this.isMainConfig = isMainConfig(config);
|
|
565
|
+
if (isMainConfig(config)) {
|
|
566
|
+
for (const [appId, appConfig] of Object.entries(config.applications)) {
|
|
567
|
+
const appOverrides = !disableOverrides ? (_c = this.overrides) == null ? void 0 : _c.applications[appId] : void 0;
|
|
568
|
+
if (isDefaultApp(appConfig)) {
|
|
569
|
+
this.defaultApplication = new DefaultApplication(appId, {
|
|
570
|
+
app: appConfig,
|
|
571
|
+
overrides: appOverrides
|
|
572
|
+
});
|
|
573
|
+
} else {
|
|
574
|
+
this.childApplications[appId] = new ChildApplication(appId, {
|
|
575
|
+
app: appConfig,
|
|
576
|
+
overrides: appOverrides
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
} else {
|
|
581
|
+
this.partOf = config.partOf;
|
|
582
|
+
const appOverrides = !disableOverrides ? (_d = this.overrides) == null ? void 0 : _d.applications[meta.fromApp] : void 0;
|
|
583
|
+
this.childApplications[meta.fromApp] = new ChildApplication(
|
|
584
|
+
meta.fromApp,
|
|
585
|
+
{
|
|
586
|
+
// we don't know routing because we're not in the main config
|
|
587
|
+
app: { routing: [] },
|
|
588
|
+
overrides: appOverrides
|
|
589
|
+
}
|
|
375
590
|
);
|
|
376
591
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
592
|
+
if (isMainConfig(config) && !this.defaultApplication) {
|
|
593
|
+
throw new MicrofrontendError(
|
|
594
|
+
`Could not find default application in microfrontends configuration`,
|
|
595
|
+
{
|
|
596
|
+
type: "application",
|
|
597
|
+
subtype: "not_found"
|
|
598
|
+
}
|
|
599
|
+
);
|
|
384
600
|
}
|
|
385
601
|
this.config = config;
|
|
386
|
-
this.name = config.name;
|
|
387
|
-
this.version = config.version;
|
|
388
602
|
this.options = config.options;
|
|
389
|
-
this
|
|
603
|
+
this.serialized = {
|
|
604
|
+
config,
|
|
605
|
+
overrides,
|
|
606
|
+
meta
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
static validate(config) {
|
|
610
|
+
const c = typeof config === "string" ? (0, import_jsonc_parser.parse)(config) : config;
|
|
611
|
+
if (isMainConfig(c)) {
|
|
612
|
+
validateConfigVersion(c.version);
|
|
613
|
+
validateConfigPaths(c.applications);
|
|
614
|
+
validateConfigDefaultApplication(c.applications);
|
|
615
|
+
}
|
|
616
|
+
return c;
|
|
617
|
+
}
|
|
618
|
+
static fromEnv({
|
|
619
|
+
meta,
|
|
620
|
+
cookies
|
|
621
|
+
}) {
|
|
622
|
+
return new MicrofrontendConfigIsomorphic({
|
|
623
|
+
config: (0, import_jsonc_parser.parse)(getConfigStringFromEnv()),
|
|
624
|
+
overrides: parseOverrides(cookies ?? []),
|
|
625
|
+
meta
|
|
626
|
+
});
|
|
390
627
|
}
|
|
391
628
|
isOverridesDisabled() {
|
|
392
629
|
var _a, _b;
|
|
393
630
|
return ((_b = (_a = this.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
394
631
|
}
|
|
395
|
-
static getConfigFromEnv() {
|
|
396
|
-
const config = process.env.MFE_CONFIG;
|
|
397
|
-
if (!config) {
|
|
398
|
-
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
399
|
-
type: "config",
|
|
400
|
-
subtype: "not_found_in_env"
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
return config;
|
|
404
|
-
}
|
|
405
|
-
static fromEnv(_) {
|
|
406
|
-
throw new Error("Not implemented");
|
|
407
|
-
}
|
|
408
632
|
getConfig() {
|
|
409
633
|
return this.config;
|
|
410
634
|
}
|
|
635
|
+
getApplicationsByType() {
|
|
636
|
+
return {
|
|
637
|
+
defaultApplication: this.defaultApplication,
|
|
638
|
+
applications: Object.values(this.childApplications)
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
getChildApplications() {
|
|
642
|
+
return Object.values(this.childApplications);
|
|
643
|
+
}
|
|
411
644
|
getAllApplications() {
|
|
412
|
-
return
|
|
645
|
+
return [
|
|
646
|
+
this.defaultApplication,
|
|
647
|
+
...Object.values(this.childApplications)
|
|
648
|
+
].filter(Boolean);
|
|
413
649
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
if (
|
|
650
|
+
getApplication(name) {
|
|
651
|
+
var _a;
|
|
652
|
+
if (((_a = this.defaultApplication) == null ? void 0 : _a.name) === name) {
|
|
653
|
+
return this.defaultApplication;
|
|
654
|
+
}
|
|
655
|
+
const app = this.childApplications[name];
|
|
656
|
+
if (!app) {
|
|
417
657
|
throw new MicrofrontendError(
|
|
418
658
|
`Could not find microfrontends configuration for application "${name}"`,
|
|
419
659
|
{
|
|
420
|
-
type: "
|
|
660
|
+
type: "application",
|
|
421
661
|
subtype: "not_found"
|
|
422
662
|
}
|
|
423
663
|
);
|
|
424
664
|
}
|
|
425
|
-
return
|
|
665
|
+
return app;
|
|
426
666
|
}
|
|
427
667
|
getApplicationByProjectId(projectId) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
668
|
+
var _a, _b;
|
|
669
|
+
if (((_b = (_a = this.defaultApplication) == null ? void 0 : _a.vercel) == null ? void 0 : _b.projectId) === projectId) {
|
|
670
|
+
return this.defaultApplication;
|
|
671
|
+
}
|
|
672
|
+
return Object.values(this.childApplications).find(
|
|
673
|
+
(app) => {
|
|
674
|
+
var _a2;
|
|
675
|
+
return ((_a2 = app.vercel) == null ? void 0 : _a2.projectId) === projectId;
|
|
432
676
|
}
|
|
433
677
|
);
|
|
434
678
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
679
|
+
/**
|
|
680
|
+
* Returns the default application. This can throw if the default application
|
|
681
|
+
* is undefined ( )
|
|
682
|
+
*/
|
|
683
|
+
getDefaultApplication() {
|
|
684
|
+
if (!this.defaultApplication) {
|
|
438
685
|
throw new MicrofrontendError(
|
|
439
|
-
`Could not find default
|
|
686
|
+
`Could not find default application in microfrontends configuration`,
|
|
440
687
|
{
|
|
441
|
-
type: "
|
|
688
|
+
type: "application",
|
|
442
689
|
subtype: "not_found"
|
|
443
690
|
}
|
|
444
691
|
);
|
|
445
692
|
}
|
|
446
|
-
return
|
|
693
|
+
return this.defaultApplication;
|
|
447
694
|
}
|
|
448
695
|
/**
|
|
449
696
|
* Returns the configured port for the local proxy
|
|
@@ -458,55 +705,147 @@ var MicrofrontendConfigCommon = class {
|
|
|
458
705
|
* NOTE: This is used when writing the config to disk and must always match the input Schema
|
|
459
706
|
*/
|
|
460
707
|
toSchemaJson() {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
708
|
+
return this.serialized.config;
|
|
709
|
+
}
|
|
710
|
+
toClientConfig() {
|
|
711
|
+
const applications = Object.fromEntries(
|
|
712
|
+
Object.entries(this.childApplications).map(([name, application]) => [
|
|
713
|
+
name,
|
|
714
|
+
{
|
|
715
|
+
default: false,
|
|
716
|
+
routing: application.routing
|
|
717
|
+
}
|
|
718
|
+
])
|
|
719
|
+
);
|
|
720
|
+
if (this.defaultApplication) {
|
|
721
|
+
applications[this.defaultApplication.name] = {
|
|
722
|
+
default: true
|
|
723
|
+
};
|
|
464
724
|
}
|
|
465
|
-
return {
|
|
466
|
-
$schema: this.$schema,
|
|
467
|
-
name: this.name,
|
|
468
|
-
version: this.version,
|
|
469
|
-
options: this.options,
|
|
725
|
+
return new MicrofrontendConfigClient({
|
|
470
726
|
applications
|
|
471
|
-
};
|
|
727
|
+
});
|
|
472
728
|
}
|
|
473
729
|
serialize() {
|
|
474
|
-
|
|
475
|
-
const applications = {};
|
|
476
|
-
for (const [name, zone] of Object.entries(this.zones)) {
|
|
477
|
-
applications[name] = zone.serialize();
|
|
478
|
-
}
|
|
479
|
-
return {
|
|
480
|
-
config: {
|
|
481
|
-
name: this.name,
|
|
482
|
-
version: this.version,
|
|
483
|
-
applications,
|
|
484
|
-
options: this.options,
|
|
485
|
-
$schema: this.$schema
|
|
486
|
-
},
|
|
487
|
-
overrides: (_a = this.overrides) == null ? void 0 : _a.serialize()
|
|
488
|
-
};
|
|
730
|
+
return this.serialized;
|
|
489
731
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
732
|
+
};
|
|
733
|
+
|
|
734
|
+
// src/config/microfrontends-config/isomorphic/child.ts
|
|
735
|
+
var MicrofrontendChildConfig = class extends MicrofrontendConfigIsomorphic {
|
|
736
|
+
constructor({
|
|
737
|
+
config,
|
|
738
|
+
overrides,
|
|
739
|
+
meta
|
|
740
|
+
}) {
|
|
741
|
+
super({ config, overrides, meta });
|
|
742
|
+
this.isMainConfig = false;
|
|
743
|
+
this.partOf = config.partOf;
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
// src/config/microfrontends-config/isomorphic/main.ts
|
|
748
|
+
var MicrofrontendMainConfig = class extends MicrofrontendConfigIsomorphic {
|
|
749
|
+
constructor({
|
|
750
|
+
config,
|
|
751
|
+
overrides,
|
|
752
|
+
meta
|
|
753
|
+
}) {
|
|
754
|
+
var _a, _b, _c;
|
|
755
|
+
super({ config, overrides, meta });
|
|
756
|
+
this.isMainConfig = true;
|
|
757
|
+
const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
758
|
+
let defaultApplication;
|
|
759
|
+
for (const [appId, appConfig] of Object.entries(config.applications)) {
|
|
760
|
+
const appOverrides = !disableOverrides ? (_c = this.overrides) == null ? void 0 : _c.applications[appId] : void 0;
|
|
761
|
+
if (isDefaultApp(appConfig)) {
|
|
762
|
+
defaultApplication = new DefaultApplication(appId, {
|
|
763
|
+
app: appConfig,
|
|
764
|
+
overrides: appOverrides
|
|
765
|
+
});
|
|
766
|
+
} else {
|
|
767
|
+
this.childApplications[appId] = new ChildApplication(appId, {
|
|
768
|
+
app: appConfig,
|
|
769
|
+
overrides: appOverrides
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
if (!defaultApplication) {
|
|
774
|
+
throw new MicrofrontendError(
|
|
775
|
+
`Could not find default application in microfrontends configuration`,
|
|
776
|
+
{
|
|
777
|
+
type: "application",
|
|
778
|
+
subtype: "not_found"
|
|
779
|
+
}
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
this.defaultApplication = defaultApplication;
|
|
495
783
|
}
|
|
496
784
|
};
|
|
497
785
|
|
|
498
|
-
// src/config/
|
|
499
|
-
var
|
|
786
|
+
// src/config/microfrontends/isomorphic/index.ts
|
|
787
|
+
var Microfrontends = class {
|
|
788
|
+
constructor({
|
|
789
|
+
config,
|
|
790
|
+
overrides,
|
|
791
|
+
meta
|
|
792
|
+
}) {
|
|
793
|
+
if (isMainConfig(config)) {
|
|
794
|
+
this.config = new MicrofrontendMainConfig({ config, overrides, meta });
|
|
795
|
+
} else {
|
|
796
|
+
this.config = new MicrofrontendChildConfig({ config, overrides, meta });
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
isChildConfig() {
|
|
800
|
+
return this.config instanceof MicrofrontendChildConfig;
|
|
801
|
+
}
|
|
500
802
|
static fromEnv({
|
|
501
|
-
cookies
|
|
803
|
+
cookies,
|
|
804
|
+
meta
|
|
502
805
|
}) {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
806
|
+
const config = MicrofrontendConfigIsomorphic.fromEnv({
|
|
807
|
+
cookies,
|
|
808
|
+
meta
|
|
506
809
|
});
|
|
810
|
+
return new Microfrontends(config.serialize());
|
|
507
811
|
}
|
|
508
812
|
};
|
|
509
813
|
|
|
814
|
+
// src/routing/get-domain-from-environment.ts
|
|
815
|
+
function getDomainFromEnvironment({
|
|
816
|
+
app,
|
|
817
|
+
target
|
|
818
|
+
}) {
|
|
819
|
+
var _a;
|
|
820
|
+
const mfeProjects = JSON.parse(
|
|
821
|
+
process.env.VERCEL_MICROFRONTENDS_PROJECTS ?? "[]"
|
|
822
|
+
);
|
|
823
|
+
if (mfeProjects.length === 0) {
|
|
824
|
+
throw new Error("Missing related microfrontends project information");
|
|
825
|
+
}
|
|
826
|
+
if (!((_a = app.vercel) == null ? void 0 : _a.projectId)) {
|
|
827
|
+
throw new Error(`Missing applications[${app.name}].vercel.projectId`);
|
|
828
|
+
}
|
|
829
|
+
const vercelProject = mfeProjects.find(
|
|
830
|
+
(p) => {
|
|
831
|
+
var _a2;
|
|
832
|
+
return p.project.id === ((_a2 = app.vercel) == null ? void 0 : _a2.projectId);
|
|
833
|
+
}
|
|
834
|
+
);
|
|
835
|
+
if (!vercelProject) {
|
|
836
|
+
throw new Error(
|
|
837
|
+
`Missing related microfrontends project information for application "${app.name}"`
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
const domain = target === "preview" && vercelProject.preview.branch ? vercelProject.preview.branch : vercelProject.production.alias ?? vercelProject.production.url;
|
|
841
|
+
if (!domain) {
|
|
842
|
+
throw new Error(
|
|
843
|
+
`Missing domain for target "${target}" in application "${app.name}"`
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
return domain.startsWith("https://") ? domain : `https://${domain}`;
|
|
847
|
+
}
|
|
848
|
+
|
|
510
849
|
// src/routing/get-domain-for-current-environment.ts
|
|
511
850
|
function debugDomains(zone, env, domain) {
|
|
512
851
|
if (process.env.MFE_DEBUG === "true") {
|
|
@@ -520,34 +859,45 @@ ${line}
|
|
|
520
859
|
`);
|
|
521
860
|
}
|
|
522
861
|
}
|
|
523
|
-
function
|
|
862
|
+
function getCurrentEnvironment() {
|
|
863
|
+
const isDevelopment = !process.env.VERCEL_ENV || process.env.VERCEL_ENV === "development";
|
|
864
|
+
const isPreview = process.env.VERCEL_ENV === "preview";
|
|
865
|
+
const isProduction = process.env.VERCEL_ENV === "production";
|
|
866
|
+
if (isDevelopment) {
|
|
867
|
+
return { group: "development" };
|
|
868
|
+
} else if (isProduction) {
|
|
869
|
+
return { group: "production" };
|
|
870
|
+
} else if (isPreview) {
|
|
871
|
+
return { group: "preview" };
|
|
872
|
+
}
|
|
873
|
+
return { group: "custom", name: process.env.VERCEL_ENV };
|
|
874
|
+
}
|
|
875
|
+
function getDomainForCurrentEnvironment(config, appName, opts = {}) {
|
|
524
876
|
var _a;
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
return domain;
|
|
537
|
-
} else if (process.env.VERCEL_ENV === "preview") {
|
|
538
|
-
const MFE_PREVIEW_DOMAINS = JSON.parse(
|
|
539
|
-
process.env.MFE_PREVIEW_DOMAINS ?? "{}"
|
|
540
|
-
);
|
|
541
|
-
if (MFE_PREVIEW_DOMAINS[zoneName]) {
|
|
542
|
-
debugDomains(zoneName, "preview", MFE_PREVIEW_DOMAINS[zoneName]);
|
|
543
|
-
return MFE_PREVIEW_DOMAINS[zoneName];
|
|
877
|
+
const app = config.getApplication(appName);
|
|
878
|
+
if (!opts.ignoreOverride && ((_a = app.overrides) == null ? void 0 : _a.environment)) {
|
|
879
|
+
return app.overrides.environment.toString();
|
|
880
|
+
}
|
|
881
|
+
const { group } = getCurrentEnvironment();
|
|
882
|
+
const productionHost = config.getDefaultApplication().production.toString();
|
|
883
|
+
switch (group) {
|
|
884
|
+
case "development": {
|
|
885
|
+
const domain = ["test", "development"].includes(process.env.NODE_ENV) ? app.development.local.toString() : productionHost;
|
|
886
|
+
debugDomains(appName, "development", domain);
|
|
887
|
+
return domain;
|
|
544
888
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
889
|
+
case "preview": {
|
|
890
|
+
return getDomainFromEnvironment({ app, target: "preview" });
|
|
891
|
+
}
|
|
892
|
+
case "production": {
|
|
893
|
+
return getDomainFromEnvironment({ app, target: "production" });
|
|
894
|
+
}
|
|
895
|
+
case "custom":
|
|
896
|
+
console.warn(
|
|
897
|
+
`Custom environments are not supported in getDomainForCurrentEnvironment`
|
|
898
|
+
);
|
|
899
|
+
return productionHost;
|
|
548
900
|
}
|
|
549
|
-
debugDomains(zoneName, process.env.VERCEL_ENV, zone.production.toString());
|
|
550
|
-
return zone.production.toString();
|
|
551
901
|
}
|
|
552
902
|
|
|
553
903
|
// src/next/middleware/middleware.ts
|
|
@@ -571,167 +921,187 @@ async function verifyPreviewDomain(req, rewriteDomain) {
|
|
|
571
921
|
return !(previewResponse.status === 404 && (vercelError === "DEPLOYMENT_NOT_FOUND" || vercelError === "NOT_FOUND"));
|
|
572
922
|
}
|
|
573
923
|
function getHandler({
|
|
924
|
+
config,
|
|
574
925
|
application,
|
|
575
926
|
flagFn,
|
|
576
|
-
pattern
|
|
927
|
+
pattern,
|
|
928
|
+
production
|
|
577
929
|
}) {
|
|
578
930
|
return async (req) => {
|
|
579
|
-
var _a, _b
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
callback
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
931
|
+
var _a, _b;
|
|
932
|
+
try {
|
|
933
|
+
const pathname = req.nextUrl.pathname;
|
|
934
|
+
const search = req.nextUrl.search;
|
|
935
|
+
const proxyRouting = req.headers.get("X-Vercel-Mfe-Proxy") === "1";
|
|
936
|
+
let rewriteDomain = proxyRouting ? null : getDomainForCurrentEnvironment(config, application.name);
|
|
937
|
+
const patchedHeaders = new Headers(req.headers);
|
|
938
|
+
const responseCallbacks = [];
|
|
939
|
+
const onRewrite = (response) => {
|
|
940
|
+
for (const callback of responseCallbacks) {
|
|
941
|
+
callback(response);
|
|
942
|
+
}
|
|
943
|
+
return response;
|
|
944
|
+
};
|
|
945
|
+
if (process.env.VERCEL_ENV === "preview" && rewriteDomain) {
|
|
946
|
+
const zoneFallbackCookieName = `__zone_${application.name}_production_fallback`;
|
|
947
|
+
const assetPrefix = application.getAssetPrefix();
|
|
948
|
+
if (assetPrefix && pathname.startsWith(`/${assetPrefix}`) && ((_a = req.cookies.get(zoneFallbackCookieName)) == null ? void 0 : _a.value) === "1") {
|
|
949
|
+
rewriteDomain = production.toString();
|
|
950
|
+
} else {
|
|
951
|
+
try {
|
|
952
|
+
let deploymentFound;
|
|
953
|
+
if (req.headers.get("x-vercel-skip-deployment-existence-check")) {
|
|
954
|
+
deploymentFound = true;
|
|
955
|
+
} else {
|
|
956
|
+
deploymentFound = await verifyPreviewDomain(req, rewriteDomain);
|
|
957
|
+
}
|
|
958
|
+
if (!deploymentFound) {
|
|
959
|
+
rewriteDomain = production.toString();
|
|
960
|
+
responseCallbacks.push((response) => {
|
|
961
|
+
response.cookies.set(zoneFallbackCookieName, "1", {
|
|
962
|
+
httpOnly: true,
|
|
963
|
+
sameSite: "lax",
|
|
964
|
+
secure: true,
|
|
965
|
+
maxAge: 60
|
|
966
|
+
// 1 minute
|
|
967
|
+
});
|
|
614
968
|
});
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
969
|
+
try {
|
|
970
|
+
const existingCookie = patchedHeaders.get("cookie");
|
|
971
|
+
if (!(existingCookie == null ? void 0 : existingCookie.includes("__vercel_toolbar"))) {
|
|
972
|
+
patchedHeaders.set(
|
|
973
|
+
"cookie",
|
|
974
|
+
[`__vercel_toolbar=1`, existingCookie].join("; ")
|
|
975
|
+
);
|
|
976
|
+
responseCallbacks.push((response) => {
|
|
977
|
+
response.cookies.set("__vercel_toolbar", "1", {
|
|
978
|
+
httpOnly: false,
|
|
979
|
+
sameSite: "lax",
|
|
980
|
+
secure: true,
|
|
981
|
+
maxAge: 29030400
|
|
982
|
+
});
|
|
629
983
|
});
|
|
630
|
-
}
|
|
984
|
+
}
|
|
985
|
+
} catch (error) {
|
|
631
986
|
}
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
maxAge: 0
|
|
987
|
+
} else if (((_b = req.cookies.get(zoneFallbackCookieName)) == null ? void 0 : _b.value) === "1") {
|
|
988
|
+
responseCallbacks.push((response) => {
|
|
989
|
+
response.cookies.set(zoneFallbackCookieName, "", {
|
|
990
|
+
httpOnly: true,
|
|
991
|
+
sameSite: "lax",
|
|
992
|
+
secure: true,
|
|
993
|
+
maxAge: 0
|
|
994
|
+
});
|
|
641
995
|
});
|
|
642
|
-
}
|
|
996
|
+
}
|
|
997
|
+
} catch {
|
|
643
998
|
}
|
|
644
|
-
} catch {
|
|
645
999
|
}
|
|
646
1000
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
1001
|
+
const isFlagEnabled = async () => flagFn ? flagFn() : true;
|
|
1002
|
+
if (pattern.test(pathname) && await isFlagEnabled()) {
|
|
1003
|
+
if (proxyRouting) {
|
|
1004
|
+
const headers = new Headers(req.headers);
|
|
1005
|
+
headers.set("x-vercel-mfe-zone", application.name);
|
|
1006
|
+
return onRewrite(
|
|
1007
|
+
import_server.NextResponse.next({
|
|
1008
|
+
request: {
|
|
1009
|
+
headers
|
|
1010
|
+
},
|
|
1011
|
+
headers: {
|
|
1012
|
+
// temporary, can delete when proxyRouting flag is removed
|
|
1013
|
+
"x-vercel-mfe-middleware-sent-proxy": application.name
|
|
1014
|
+
}
|
|
1015
|
+
})
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
653
1018
|
return onRewrite(
|
|
654
|
-
import_server.NextResponse.
|
|
1019
|
+
import_server.NextResponse.rewrite(`${rewriteDomain}${pathname}${search}`, {
|
|
655
1020
|
request: {
|
|
656
|
-
headers
|
|
657
|
-
},
|
|
658
|
-
headers: {
|
|
659
|
-
// temporary, can delete when proxyRouting flag is removed
|
|
660
|
-
"x-vercel-mfe-middleware-sent-proxy": application.name
|
|
1021
|
+
headers: patchedHeaders
|
|
661
1022
|
}
|
|
662
1023
|
})
|
|
663
1024
|
);
|
|
664
1025
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
headers: patchedHeaders
|
|
669
|
-
}
|
|
670
|
-
})
|
|
671
|
-
);
|
|
1026
|
+
} catch (e) {
|
|
1027
|
+
console.error("An error occured in the microfrontends middleware:", e);
|
|
1028
|
+
throw e;
|
|
672
1029
|
}
|
|
673
1030
|
};
|
|
674
1031
|
}
|
|
675
1032
|
function getMicrofrontendsMiddleware({
|
|
676
1033
|
request,
|
|
677
|
-
flagValues
|
|
1034
|
+
flagValues,
|
|
1035
|
+
fromApp
|
|
678
1036
|
}) {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
1037
|
+
const microfrontends = Microfrontends.fromEnv({
|
|
1038
|
+
cookies: request.cookies.getAll(),
|
|
1039
|
+
meta: {
|
|
1040
|
+
fromApp
|
|
1041
|
+
}
|
|
682
1042
|
});
|
|
683
1043
|
const middlewares = [];
|
|
684
|
-
|
|
1044
|
+
if (microfrontends.config instanceof MicrofrontendChildConfig) {
|
|
1045
|
+
return middlewares;
|
|
1046
|
+
}
|
|
1047
|
+
const config = microfrontends.config;
|
|
1048
|
+
const production = config.defaultApplication.production;
|
|
1049
|
+
for (const application of config.getChildApplications()) {
|
|
685
1050
|
if (application.name === process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION) {
|
|
686
1051
|
continue;
|
|
687
1052
|
}
|
|
688
|
-
if (
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
for (const path of pathGroup.paths) {
|
|
714
|
-
const pattern = (0, import_path_to_regexp.pathToRegexp)(path);
|
|
715
|
-
middlewares.push({
|
|
716
|
-
src: pattern,
|
|
717
|
-
fn: getHandler({
|
|
718
|
-
application,
|
|
719
|
-
flagFn,
|
|
720
|
-
pattern
|
|
721
|
-
})
|
|
722
|
-
});
|
|
1053
|
+
if (process.env.VERCEL_ENV === "preview") {
|
|
1054
|
+
const pattern = (0, import_path_to_regexp3.pathToRegexp)(`/${application.getAssetPrefix()}/:path+`);
|
|
1055
|
+
middlewares.push({
|
|
1056
|
+
src: pattern,
|
|
1057
|
+
fn: getHandler({
|
|
1058
|
+
config,
|
|
1059
|
+
application,
|
|
1060
|
+
pattern,
|
|
1061
|
+
production
|
|
1062
|
+
})
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
for (const pathGroup of application.routing) {
|
|
1066
|
+
if (process.env.VERCEL_ENV === "preview" || pathGroup.flag) {
|
|
1067
|
+
const flagName = pathGroup.flag;
|
|
1068
|
+
let flagFn;
|
|
1069
|
+
if (flagName) {
|
|
1070
|
+
flagFn = flagValues == null ? void 0 : flagValues[flagName];
|
|
1071
|
+
if (!flagFn) {
|
|
1072
|
+
throw new Error(
|
|
1073
|
+
`Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${application.name} but not found in provided flag values.`
|
|
1074
|
+
);
|
|
723
1075
|
}
|
|
724
1076
|
}
|
|
1077
|
+
for (const path of pathGroup.paths) {
|
|
1078
|
+
const pattern = (0, import_path_to_regexp3.pathToRegexp)(path);
|
|
1079
|
+
middlewares.push({
|
|
1080
|
+
src: pattern,
|
|
1081
|
+
fn: getHandler({
|
|
1082
|
+
config,
|
|
1083
|
+
application,
|
|
1084
|
+
flagFn,
|
|
1085
|
+
pattern,
|
|
1086
|
+
production
|
|
1087
|
+
})
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
725
1090
|
}
|
|
726
1091
|
}
|
|
727
1092
|
}
|
|
728
1093
|
return middlewares;
|
|
729
1094
|
}
|
|
730
|
-
async function runMicrofrontendsMiddleware(
|
|
1095
|
+
async function runMicrofrontendsMiddleware({
|
|
1096
|
+
request,
|
|
1097
|
+
fromApp,
|
|
1098
|
+
flagValues
|
|
1099
|
+
}) {
|
|
731
1100
|
const pathname = request.nextUrl.pathname;
|
|
732
1101
|
const middlewares = getMicrofrontendsMiddleware({
|
|
733
1102
|
request,
|
|
734
|
-
flagValues
|
|
1103
|
+
flagValues,
|
|
1104
|
+
fromApp
|
|
735
1105
|
});
|
|
736
1106
|
for (const mware of middlewares) {
|
|
737
1107
|
if (typeof mware.src === "string" ? pathname === mware.src : mware.src.test(pathname)) {
|