@vercel/microfrontends 0.13.0 → 0.15.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/README.md +3 -3
- package/dist/bin/cli.cjs +403 -1627
- package/dist/config.cjs +460 -1004
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.ts +4 -25
- package/dist/config.js +456 -983
- package/dist/config.js.map +1 -1
- package/dist/{index-83133f2d.d.ts → index-bf67a461.d.ts} +3 -10
- package/dist/{v2/microfrontends → microfrontends}/server.cjs +128 -194
- package/dist/microfrontends/server.cjs.map +1 -0
- package/dist/{v2/microfrontends → microfrontends}/server.d.ts +6 -5
- package/dist/{v2/microfrontends → microfrontends}/server.js +125 -191
- package/dist/microfrontends/server.js.map +1 -0
- package/dist/{v2/microfrontends.cjs → microfrontends.cjs} +21 -35
- package/dist/microfrontends.cjs.map +1 -0
- package/dist/{v2/microfrontends.d.ts → microfrontends.d.ts} +4 -3
- package/dist/{v2/microfrontends.js → microfrontends.js} +20 -34
- 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 +1323 -1024
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.d.ts +1 -1
- package/dist/next/config.js +1327 -1028
- 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 +14 -3
- package/dist/next/endpoints.js +77 -18
- package/dist/next/endpoints.js.map +1 -1
- package/dist/next/middleware.cjs +745 -425
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.d.ts +10 -5
- package/dist/next/middleware.js +745 -425
- package/dist/next/middleware.js.map +1 -1
- package/dist/next/testing.cjs +595 -1032
- package/dist/next/testing.cjs.map +1 -1
- package/dist/next/testing.d.ts +14 -12
- package/dist/next/testing.js +589 -1016
- 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/routing.cjs +19 -0
- package/dist/routing.cjs.map +1 -0
- package/dist/routing.d.ts +26 -0
- package/dist/routing.js +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/schema.js.map +1 -0
- package/dist/{types-a995174e.d.ts → types-a29d224a.d.ts} +1 -7
- package/dist/{types-15b7f215.d.ts → types-cfe3308b.d.ts} +1 -1
- package/dist/types-fc30696d.d.ts +11 -0
- package/dist/utils/mfe-port.cjs +254 -1362
- package/dist/utils/mfe-port.cjs.map +1 -1
- package/dist/utils/mfe-port.js +250 -1358
- package/dist/utils/mfe-port.js.map +1 -1
- package/dist/validation.cjs +31 -365
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.d.ts +3 -152
- package/dist/validation.js +30 -363
- package/dist/validation.js.map +1 -1
- package/package.json +32 -80
- 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 -723
- package/dist/v2/config.cjs.map +0 -1
- package/dist/v2/config.d.ts +0 -3
- package/dist/v2/config.js +0 -698
- 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 -2132
- 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 -2097
- 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 -15
- package/dist/v2/next/endpoints.js +0 -116
- package/dist/v2/next/endpoints.js.map +0 -1
- package/dist/v2/next/middleware.cjs +0 -1143
- package/dist/v2/next/middleware.cjs.map +0 -1
- package/dist/v2/next/middleware.d.ts +0 -29
- package/dist/v2/next/middleware.js +0 -1115
- package/dist/v2/next/middleware.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/schema.cjs.map +0 -1
- package/dist/v2/schema.d.ts +0 -1
- package/schema/schema-v2.json +0 -270
- /package/dist/{v2/schema.js.map → routing.js.map} +0 -0
- /package/dist/{v2/schema.js → schema.js} +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,299 @@ 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 tokens = (0, import_path_to_regexp2.parse)(path);
|
|
275
|
+
for (const token of tokens.slice(0, -1)) {
|
|
276
|
+
if (typeof token !== "string") {
|
|
277
|
+
errors.push(
|
|
278
|
+
`Path ${path} may only have a :wildcard in the last path component`
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
const existing = pathsByApplicationId.get(path);
|
|
283
|
+
if (existing) {
|
|
284
|
+
existing.applications.push(id);
|
|
285
|
+
} else {
|
|
286
|
+
pathsByApplicationId.set(path, {
|
|
287
|
+
applications: [id],
|
|
288
|
+
matcher: (0, import_path_to_regexp2.pathToRegexp)(path),
|
|
289
|
+
applicationId: id
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
193
294
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
295
|
+
const entries = Array.from(pathsByApplicationId.entries());
|
|
296
|
+
entries.forEach(([path, { applications: ids, matcher, applicationId }]) => {
|
|
297
|
+
if (ids.length > 1) {
|
|
298
|
+
errors.push(
|
|
299
|
+
`Duplicate path "${path}" for applications "${ids.join(", ")}"`
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
entries.forEach(
|
|
303
|
+
([
|
|
304
|
+
matchPath,
|
|
305
|
+
{ applications: matchIds, applicationId: matchApplicationId }
|
|
306
|
+
]) => {
|
|
307
|
+
if (path === matchPath) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if (applicationId === matchApplicationId) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
if (matcher.test(matchPath)) {
|
|
314
|
+
const source = `"${path}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
315
|
+
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
316
|
+
errors.push(
|
|
317
|
+
`Overlapping path detected between ${source} and ${destination}`
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
});
|
|
323
|
+
if (errors.length) {
|
|
324
|
+
throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
|
|
325
|
+
type: "config",
|
|
326
|
+
subtype: "conflicting_paths"
|
|
203
327
|
});
|
|
204
|
-
return overridesConfig;
|
|
205
328
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
329
|
+
};
|
|
330
|
+
var validateAppPaths = (name, app) => {
|
|
331
|
+
for (const group of app.routing) {
|
|
332
|
+
for (const p of group.paths) {
|
|
333
|
+
if (p === "/") {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
if (p.endsWith("/")) {
|
|
337
|
+
throw new MicrofrontendError(
|
|
338
|
+
`Invalid path for application "${name}". ${p} must not end with a slash.`,
|
|
339
|
+
{ type: "application", subtype: "invalid_path" }
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
if (!p.startsWith("/")) {
|
|
343
|
+
throw new MicrofrontendError(
|
|
344
|
+
`Invalid path for application "${name}". ${p} must start with a slash.`,
|
|
345
|
+
{ type: "application", subtype: "invalid_path" }
|
|
346
|
+
);
|
|
347
|
+
}
|
|
217
348
|
}
|
|
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
349
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
)}$`
|
|
229
|
-
).test(domain);
|
|
350
|
+
};
|
|
351
|
+
var validateConfigDefaultApplication = (applicationConfigsById) => {
|
|
352
|
+
if (!applicationConfigsById) {
|
|
353
|
+
return;
|
|
230
354
|
}
|
|
231
|
-
|
|
232
|
-
|
|
355
|
+
const applicationsWithRouting = Object.entries(applicationConfigsById).filter(
|
|
356
|
+
([, app]) => !isDefaultApp(app)
|
|
357
|
+
);
|
|
358
|
+
const applicationsWithRoutingNames = applicationsWithRouting.map(
|
|
359
|
+
([key]) => key
|
|
360
|
+
);
|
|
361
|
+
const numApplications = Object.keys(applicationConfigsById).length;
|
|
362
|
+
const numApplicationsWithRouting = applicationsWithRoutingNames.length;
|
|
363
|
+
const numApplicationsWithoutRouting = numApplications - numApplicationsWithRouting;
|
|
364
|
+
if (numApplicationsWithoutRouting === 0) {
|
|
365
|
+
throw new MicrofrontendError(
|
|
366
|
+
`No default application found. At least one application needs to be the default by omitting routing.`,
|
|
367
|
+
{ type: "config", subtype: "no_default_application" }
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
if (numApplicationsWithoutRouting > 1) {
|
|
371
|
+
throw new MicrofrontendError(
|
|
372
|
+
`Only one application can omit "routing". Found ${applicationsWithRoutingNames.length - Object.keys(applicationConfigsById).length > 1}.`,
|
|
373
|
+
{ type: "config", subtype: "multiple_default_applications" }
|
|
374
|
+
);
|
|
233
375
|
}
|
|
234
376
|
};
|
|
235
|
-
var Overrides = _Overrides;
|
|
236
|
-
Overrides.overrideEnvCookiePrefix = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
237
377
|
|
|
238
|
-
// src/config/
|
|
378
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
|
|
379
|
+
var PREFIX = "vc-ap";
|
|
380
|
+
function generateAssetPrefixFromName({
|
|
381
|
+
name
|
|
382
|
+
}) {
|
|
383
|
+
if (!name) {
|
|
384
|
+
throw new Error("Name is required to generate an asset prefix");
|
|
385
|
+
}
|
|
386
|
+
return `${PREFIX}-${name}`;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-port.ts
|
|
390
|
+
function generatePortFromName({
|
|
391
|
+
name,
|
|
392
|
+
minPort = 3e3,
|
|
393
|
+
maxPort = 8e3
|
|
394
|
+
}) {
|
|
395
|
+
if (!name) {
|
|
396
|
+
throw new Error("Name is required to generate a port");
|
|
397
|
+
}
|
|
398
|
+
let hash = 0;
|
|
399
|
+
for (let i = 0; i < name.length; i++) {
|
|
400
|
+
hash = (hash << 5) - hash + name.charCodeAt(i);
|
|
401
|
+
hash |= 0;
|
|
402
|
+
}
|
|
403
|
+
hash = Math.abs(hash);
|
|
404
|
+
const range = maxPort - minPort;
|
|
405
|
+
const port = minPort + hash % range;
|
|
406
|
+
return port;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// src/config/microfrontends-config/isomorphic/host.ts
|
|
239
410
|
var Host = class {
|
|
240
|
-
constructor(
|
|
241
|
-
|
|
411
|
+
constructor(hostConfig, options) {
|
|
412
|
+
const { protocol = "https", host, port } = hostConfig;
|
|
413
|
+
this.protocol = protocol;
|
|
242
414
|
this.host = host;
|
|
243
415
|
this.port = Host.getPort({ port, protocol: this.protocol });
|
|
244
|
-
this.
|
|
245
|
-
protocol,
|
|
246
|
-
host,
|
|
247
|
-
...port ? { port } : void 0
|
|
248
|
-
};
|
|
416
|
+
this.local = options == null ? void 0 : options.isLocal;
|
|
249
417
|
}
|
|
250
418
|
isLocal() {
|
|
251
|
-
return this.host === "localhost" || this.host === "127.0.0.1";
|
|
419
|
+
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
252
420
|
}
|
|
253
421
|
static getPort({
|
|
254
422
|
protocol,
|
|
@@ -274,176 +442,234 @@ var Host = class {
|
|
|
274
442
|
const url = `${this.protocol}://${this.host}${this.isDefaultPort() && !includeDefaultPort ? "" : `:${this.port}`}`;
|
|
275
443
|
return new URL(url);
|
|
276
444
|
}
|
|
277
|
-
|
|
278
|
-
|
|
445
|
+
};
|
|
446
|
+
var LocalHost = class extends Host {
|
|
447
|
+
constructor({
|
|
448
|
+
appName,
|
|
449
|
+
...hostConfig
|
|
450
|
+
}) {
|
|
451
|
+
const host = hostConfig.host ?? "localhost";
|
|
452
|
+
const port = hostConfig.port ?? generatePortFromName({ name: appName });
|
|
453
|
+
const protocol = hostConfig.protocol ?? "http";
|
|
454
|
+
super({ protocol, host, port });
|
|
279
455
|
}
|
|
280
456
|
};
|
|
281
457
|
|
|
282
|
-
// src/config/
|
|
458
|
+
// src/config/microfrontends-config/isomorphic/application.ts
|
|
283
459
|
var Application = class {
|
|
284
460
|
constructor(name, {
|
|
285
461
|
app,
|
|
286
|
-
overrides
|
|
462
|
+
overrides,
|
|
463
|
+
isDefault
|
|
287
464
|
}) {
|
|
288
|
-
|
|
465
|
+
var _a, _b;
|
|
289
466
|
this.name = name;
|
|
290
|
-
this.default = app.default;
|
|
291
|
-
this.routing = app.routing;
|
|
292
467
|
this.development = {
|
|
293
|
-
local: new
|
|
294
|
-
|
|
468
|
+
local: new LocalHost({
|
|
469
|
+
appName: name,
|
|
470
|
+
...(_a = app.development) == null ? void 0 : _a.local
|
|
471
|
+
}),
|
|
472
|
+
fallback: ((_b = app.development) == null ? void 0 : _b.fallback) ? new Host(app.development.fallback) : void 0
|
|
295
473
|
};
|
|
296
|
-
this.production = new Host(app.production);
|
|
474
|
+
this.production = app.production ? new Host(app.production) : void 0;
|
|
297
475
|
this.vercel = app.vercel;
|
|
298
476
|
this.overrides = (overrides == null ? void 0 : overrides.environment) ? {
|
|
299
477
|
environment: new Host(overrides.environment)
|
|
300
478
|
} : void 0;
|
|
479
|
+
this.default = isDefault ?? false;
|
|
480
|
+
this.serialized = app;
|
|
301
481
|
}
|
|
302
482
|
isDefault() {
|
|
303
483
|
return this.default;
|
|
304
484
|
}
|
|
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
|
-
}
|
|
485
|
+
getAssetPrefix() {
|
|
486
|
+
return generateAssetPrefixFromName({ name: this.name });
|
|
332
487
|
}
|
|
333
488
|
serialize() {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
489
|
+
return this.serialized;
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
var DefaultApplication = class extends Application {
|
|
493
|
+
constructor(name, {
|
|
494
|
+
app,
|
|
495
|
+
overrides
|
|
496
|
+
}) {
|
|
497
|
+
super(name, {
|
|
498
|
+
app,
|
|
499
|
+
overrides,
|
|
500
|
+
isDefault: true
|
|
501
|
+
});
|
|
502
|
+
this.default = true;
|
|
503
|
+
this.production = new Host(app.production);
|
|
504
|
+
}
|
|
505
|
+
getAssetPrefix() {
|
|
506
|
+
return "";
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
var ChildApplication = class extends Application {
|
|
510
|
+
constructor(name, {
|
|
511
|
+
app,
|
|
512
|
+
overrides
|
|
513
|
+
}) {
|
|
514
|
+
ChildApplication.validate(name, app);
|
|
515
|
+
super(name, {
|
|
516
|
+
app,
|
|
517
|
+
overrides,
|
|
518
|
+
isDefault: false
|
|
519
|
+
});
|
|
520
|
+
this.default = false;
|
|
521
|
+
this.routing = app.routing;
|
|
522
|
+
}
|
|
523
|
+
static validate(name, app) {
|
|
524
|
+
validateAppPaths(name, app);
|
|
356
525
|
}
|
|
357
526
|
};
|
|
358
527
|
|
|
359
|
-
// src/config/
|
|
360
|
-
var SUPPORTED_VERSIONS = ["1"];
|
|
528
|
+
// src/config/microfrontends-config/isomorphic/constants.ts
|
|
361
529
|
var DEFAULT_LOCAL_PROXY_PORT = 3024;
|
|
362
|
-
|
|
530
|
+
|
|
531
|
+
// src/config/microfrontends-config/isomorphic/index.ts
|
|
532
|
+
var MicrofrontendConfigIsomorphic = class {
|
|
363
533
|
constructor({
|
|
364
534
|
config,
|
|
365
|
-
overrides
|
|
535
|
+
overrides,
|
|
536
|
+
meta
|
|
366
537
|
}) {
|
|
367
|
-
this.
|
|
368
|
-
var _a, _b, _c;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
538
|
+
this.childApplications = {};
|
|
539
|
+
var _a, _b, _c, _d;
|
|
540
|
+
MicrofrontendConfigIsomorphic.validate(config);
|
|
541
|
+
const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
542
|
+
this.overrides = overrides && !disableOverrides ? overrides : void 0;
|
|
543
|
+
this.isMainConfig = isMainConfig(config);
|
|
544
|
+
if (isMainConfig(config)) {
|
|
545
|
+
for (const [appId, appConfig] of Object.entries(config.applications)) {
|
|
546
|
+
const appOverrides = !disableOverrides ? (_c = this.overrides) == null ? void 0 : _c.applications[appId] : void 0;
|
|
547
|
+
if (isDefaultApp(appConfig)) {
|
|
548
|
+
this.defaultApplication = new DefaultApplication(appId, {
|
|
549
|
+
app: appConfig,
|
|
550
|
+
overrides: appOverrides
|
|
551
|
+
});
|
|
552
|
+
} else {
|
|
553
|
+
this.childApplications[appId] = new ChildApplication(appId, {
|
|
554
|
+
app: appConfig,
|
|
555
|
+
overrides: appOverrides
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
} else {
|
|
560
|
+
this.partOf = config.partOf;
|
|
561
|
+
const appOverrides = !disableOverrides ? (_d = this.overrides) == null ? void 0 : _d.applications[meta.fromApp] : void 0;
|
|
562
|
+
this.childApplications[meta.fromApp] = new ChildApplication(
|
|
563
|
+
meta.fromApp,
|
|
564
|
+
{
|
|
565
|
+
// we don't know routing because we're not in the main config
|
|
566
|
+
app: { routing: [] },
|
|
567
|
+
overrides: appOverrides
|
|
568
|
+
}
|
|
375
569
|
);
|
|
376
570
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
571
|
+
if (isMainConfig(config) && !this.defaultApplication) {
|
|
572
|
+
throw new MicrofrontendError(
|
|
573
|
+
`Could not find default application in microfrontends configuration`,
|
|
574
|
+
{
|
|
575
|
+
type: "application",
|
|
576
|
+
subtype: "not_found"
|
|
577
|
+
}
|
|
578
|
+
);
|
|
384
579
|
}
|
|
385
580
|
this.config = config;
|
|
386
|
-
this.name = config.name;
|
|
387
|
-
this.version = config.version;
|
|
388
581
|
this.options = config.options;
|
|
389
|
-
this
|
|
582
|
+
this.serialized = {
|
|
583
|
+
config,
|
|
584
|
+
overrides,
|
|
585
|
+
meta
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
static validate(config) {
|
|
589
|
+
const c = typeof config === "string" ? (0, import_jsonc_parser.parse)(config) : config;
|
|
590
|
+
if (isMainConfig(c)) {
|
|
591
|
+
validateConfigVersion(c.version);
|
|
592
|
+
validateConfigPaths(c.applications);
|
|
593
|
+
validateConfigDefaultApplication(c.applications);
|
|
594
|
+
}
|
|
595
|
+
return c;
|
|
596
|
+
}
|
|
597
|
+
static fromEnv({
|
|
598
|
+
meta,
|
|
599
|
+
cookies
|
|
600
|
+
}) {
|
|
601
|
+
return new MicrofrontendConfigIsomorphic({
|
|
602
|
+
config: (0, import_jsonc_parser.parse)(getConfigStringFromEnv()),
|
|
603
|
+
overrides: parseOverrides(cookies ?? []),
|
|
604
|
+
meta
|
|
605
|
+
});
|
|
390
606
|
}
|
|
391
607
|
isOverridesDisabled() {
|
|
392
608
|
var _a, _b;
|
|
393
609
|
return ((_b = (_a = this.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
394
610
|
}
|
|
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
611
|
getConfig() {
|
|
409
612
|
return this.config;
|
|
410
613
|
}
|
|
614
|
+
getApplicationsByType() {
|
|
615
|
+
return {
|
|
616
|
+
defaultApplication: this.defaultApplication,
|
|
617
|
+
applications: Object.values(this.childApplications)
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
getChildApplications() {
|
|
621
|
+
return Object.values(this.childApplications);
|
|
622
|
+
}
|
|
411
623
|
getAllApplications() {
|
|
412
|
-
return
|
|
624
|
+
return [
|
|
625
|
+
this.defaultApplication,
|
|
626
|
+
...Object.values(this.childApplications)
|
|
627
|
+
].filter(Boolean);
|
|
413
628
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
if (
|
|
629
|
+
getApplication(name) {
|
|
630
|
+
var _a;
|
|
631
|
+
if (((_a = this.defaultApplication) == null ? void 0 : _a.name) === name) {
|
|
632
|
+
return this.defaultApplication;
|
|
633
|
+
}
|
|
634
|
+
const app = this.childApplications[name];
|
|
635
|
+
if (!app) {
|
|
417
636
|
throw new MicrofrontendError(
|
|
418
637
|
`Could not find microfrontends configuration for application "${name}"`,
|
|
419
638
|
{
|
|
420
|
-
type: "
|
|
639
|
+
type: "application",
|
|
421
640
|
subtype: "not_found"
|
|
422
641
|
}
|
|
423
642
|
);
|
|
424
643
|
}
|
|
425
|
-
return
|
|
644
|
+
return app;
|
|
426
645
|
}
|
|
427
646
|
getApplicationByProjectId(projectId) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
647
|
+
var _a, _b;
|
|
648
|
+
if (((_b = (_a = this.defaultApplication) == null ? void 0 : _a.vercel) == null ? void 0 : _b.projectId) === projectId) {
|
|
649
|
+
return this.defaultApplication;
|
|
650
|
+
}
|
|
651
|
+
return Object.values(this.childApplications).find(
|
|
652
|
+
(app) => {
|
|
653
|
+
var _a2;
|
|
654
|
+
return ((_a2 = app.vercel) == null ? void 0 : _a2.projectId) === projectId;
|
|
432
655
|
}
|
|
433
656
|
);
|
|
434
657
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
658
|
+
/**
|
|
659
|
+
* Returns the default application. This can throw if the default application
|
|
660
|
+
* is undefined ( )
|
|
661
|
+
*/
|
|
662
|
+
getDefaultApplication() {
|
|
663
|
+
if (!this.defaultApplication) {
|
|
438
664
|
throw new MicrofrontendError(
|
|
439
|
-
`Could not find default
|
|
665
|
+
`Could not find default application in microfrontends configuration`,
|
|
440
666
|
{
|
|
441
|
-
type: "
|
|
667
|
+
type: "application",
|
|
442
668
|
subtype: "not_found"
|
|
443
669
|
}
|
|
444
670
|
);
|
|
445
671
|
}
|
|
446
|
-
return
|
|
672
|
+
return this.defaultApplication;
|
|
447
673
|
}
|
|
448
674
|
/**
|
|
449
675
|
* Returns the configured port for the local proxy
|
|
@@ -458,55 +684,147 @@ var MicrofrontendConfigCommon = class {
|
|
|
458
684
|
* NOTE: This is used when writing the config to disk and must always match the input Schema
|
|
459
685
|
*/
|
|
460
686
|
toSchemaJson() {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
687
|
+
return this.serialized.config;
|
|
688
|
+
}
|
|
689
|
+
toClientConfig() {
|
|
690
|
+
const applications = Object.fromEntries(
|
|
691
|
+
Object.entries(this.childApplications).map(([name, application]) => [
|
|
692
|
+
name,
|
|
693
|
+
{
|
|
694
|
+
default: false,
|
|
695
|
+
routing: application.routing
|
|
696
|
+
}
|
|
697
|
+
])
|
|
698
|
+
);
|
|
699
|
+
if (this.defaultApplication) {
|
|
700
|
+
applications[this.defaultApplication.name] = {
|
|
701
|
+
default: true
|
|
702
|
+
};
|
|
464
703
|
}
|
|
465
|
-
return {
|
|
466
|
-
$schema: this.$schema,
|
|
467
|
-
name: this.name,
|
|
468
|
-
version: this.version,
|
|
469
|
-
options: this.options,
|
|
704
|
+
return new MicrofrontendConfigClient({
|
|
470
705
|
applications
|
|
471
|
-
};
|
|
706
|
+
});
|
|
472
707
|
}
|
|
473
708
|
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
|
-
};
|
|
709
|
+
return this.serialized;
|
|
489
710
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
// src/config/microfrontends-config/isomorphic/child.ts
|
|
714
|
+
var MicrofrontendChildConfig = class extends MicrofrontendConfigIsomorphic {
|
|
715
|
+
constructor({
|
|
716
|
+
config,
|
|
717
|
+
overrides,
|
|
718
|
+
meta
|
|
719
|
+
}) {
|
|
720
|
+
super({ config, overrides, meta });
|
|
721
|
+
this.isMainConfig = false;
|
|
722
|
+
this.partOf = config.partOf;
|
|
495
723
|
}
|
|
496
724
|
};
|
|
497
725
|
|
|
498
|
-
// src/config/
|
|
499
|
-
var
|
|
726
|
+
// src/config/microfrontends-config/isomorphic/main.ts
|
|
727
|
+
var MicrofrontendMainConfig = class extends MicrofrontendConfigIsomorphic {
|
|
728
|
+
constructor({
|
|
729
|
+
config,
|
|
730
|
+
overrides,
|
|
731
|
+
meta
|
|
732
|
+
}) {
|
|
733
|
+
var _a, _b, _c;
|
|
734
|
+
super({ config, overrides, meta });
|
|
735
|
+
this.isMainConfig = true;
|
|
736
|
+
const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
737
|
+
let defaultApplication;
|
|
738
|
+
for (const [appId, appConfig] of Object.entries(config.applications)) {
|
|
739
|
+
const appOverrides = !disableOverrides ? (_c = this.overrides) == null ? void 0 : _c.applications[appId] : void 0;
|
|
740
|
+
if (isDefaultApp(appConfig)) {
|
|
741
|
+
defaultApplication = new DefaultApplication(appId, {
|
|
742
|
+
app: appConfig,
|
|
743
|
+
overrides: appOverrides
|
|
744
|
+
});
|
|
745
|
+
} else {
|
|
746
|
+
this.childApplications[appId] = new ChildApplication(appId, {
|
|
747
|
+
app: appConfig,
|
|
748
|
+
overrides: appOverrides
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if (!defaultApplication) {
|
|
753
|
+
throw new MicrofrontendError(
|
|
754
|
+
`Could not find default application in microfrontends configuration`,
|
|
755
|
+
{
|
|
756
|
+
type: "application",
|
|
757
|
+
subtype: "not_found"
|
|
758
|
+
}
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
this.defaultApplication = defaultApplication;
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
|
|
765
|
+
// src/config/microfrontends/isomorphic/index.ts
|
|
766
|
+
var Microfrontends = class {
|
|
767
|
+
constructor({
|
|
768
|
+
config,
|
|
769
|
+
overrides,
|
|
770
|
+
meta
|
|
771
|
+
}) {
|
|
772
|
+
if (isMainConfig(config)) {
|
|
773
|
+
this.config = new MicrofrontendMainConfig({ config, overrides, meta });
|
|
774
|
+
} else {
|
|
775
|
+
this.config = new MicrofrontendChildConfig({ config, overrides, meta });
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
isChildConfig() {
|
|
779
|
+
return this.config instanceof MicrofrontendChildConfig;
|
|
780
|
+
}
|
|
500
781
|
static fromEnv({
|
|
501
|
-
cookies
|
|
782
|
+
cookies,
|
|
783
|
+
meta
|
|
502
784
|
}) {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
785
|
+
const config = MicrofrontendConfigIsomorphic.fromEnv({
|
|
786
|
+
cookies,
|
|
787
|
+
meta
|
|
506
788
|
});
|
|
789
|
+
return new Microfrontends(config.serialize());
|
|
507
790
|
}
|
|
508
791
|
};
|
|
509
792
|
|
|
793
|
+
// src/routing/get-domain-from-environment.ts
|
|
794
|
+
function getDomainFromEnvironment({
|
|
795
|
+
app,
|
|
796
|
+
target
|
|
797
|
+
}) {
|
|
798
|
+
var _a;
|
|
799
|
+
const mfeProjects = JSON.parse(
|
|
800
|
+
process.env.VERCEL_MICROFRONTENDS_PROJECTS ?? "[]"
|
|
801
|
+
);
|
|
802
|
+
if (mfeProjects.length === 0) {
|
|
803
|
+
throw new Error("Missing related microfrontends project information");
|
|
804
|
+
}
|
|
805
|
+
if (!((_a = app.vercel) == null ? void 0 : _a.projectId)) {
|
|
806
|
+
throw new Error(`Missing applications[${app.name}].vercel.projectId`);
|
|
807
|
+
}
|
|
808
|
+
const vercelProject = mfeProjects.find(
|
|
809
|
+
(p) => {
|
|
810
|
+
var _a2;
|
|
811
|
+
return p.project.id === ((_a2 = app.vercel) == null ? void 0 : _a2.projectId);
|
|
812
|
+
}
|
|
813
|
+
);
|
|
814
|
+
if (!vercelProject) {
|
|
815
|
+
throw new Error(
|
|
816
|
+
`Missing related microfrontends project information for application "${app.name}"`
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
const domain = target === "preview" && vercelProject.preview.branch ? vercelProject.preview.branch : vercelProject.production.alias ?? vercelProject.production.url;
|
|
820
|
+
if (!domain) {
|
|
821
|
+
throw new Error(
|
|
822
|
+
`Missing domain for target "${target}" in application "${app.name}"`
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
return domain.startsWith("https://") ? domain : `https://${domain}`;
|
|
826
|
+
}
|
|
827
|
+
|
|
510
828
|
// src/routing/get-domain-for-current-environment.ts
|
|
511
829
|
function debugDomains(zone, env, domain) {
|
|
512
830
|
if (process.env.MFE_DEBUG === "true") {
|
|
@@ -520,34 +838,45 @@ ${line}
|
|
|
520
838
|
`);
|
|
521
839
|
}
|
|
522
840
|
}
|
|
523
|
-
function
|
|
841
|
+
function getCurrentEnvironment() {
|
|
842
|
+
const isDevelopment = !process.env.VERCEL_ENV || process.env.VERCEL_ENV === "development";
|
|
843
|
+
const isPreview = process.env.VERCEL_ENV === "preview";
|
|
844
|
+
const isProduction = process.env.VERCEL_ENV === "production";
|
|
845
|
+
if (isDevelopment) {
|
|
846
|
+
return { group: "development" };
|
|
847
|
+
} else if (isProduction) {
|
|
848
|
+
return { group: "production" };
|
|
849
|
+
} else if (isPreview) {
|
|
850
|
+
return { group: "preview" };
|
|
851
|
+
}
|
|
852
|
+
return { group: "custom", name: process.env.VERCEL_ENV };
|
|
853
|
+
}
|
|
854
|
+
function getDomainForCurrentEnvironment(config, appName, opts = {}) {
|
|
524
855
|
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];
|
|
856
|
+
const app = config.getApplication(appName);
|
|
857
|
+
if (!opts.ignoreOverride && ((_a = app.overrides) == null ? void 0 : _a.environment)) {
|
|
858
|
+
return app.overrides.environment.toString();
|
|
859
|
+
}
|
|
860
|
+
const { group } = getCurrentEnvironment();
|
|
861
|
+
const productionHost = config.getDefaultApplication().production.toString();
|
|
862
|
+
switch (group) {
|
|
863
|
+
case "development": {
|
|
864
|
+
const domain = ["test", "development"].includes(process.env.NODE_ENV) ? app.development.local.toString() : productionHost;
|
|
865
|
+
debugDomains(appName, "development", domain);
|
|
866
|
+
return domain;
|
|
544
867
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
868
|
+
case "preview": {
|
|
869
|
+
return getDomainFromEnvironment({ app, target: "preview" });
|
|
870
|
+
}
|
|
871
|
+
case "production": {
|
|
872
|
+
return getDomainFromEnvironment({ app, target: "production" });
|
|
873
|
+
}
|
|
874
|
+
case "custom":
|
|
875
|
+
console.warn(
|
|
876
|
+
`Custom environments are not supported in getDomainForCurrentEnvironment`
|
|
877
|
+
);
|
|
878
|
+
return productionHost;
|
|
548
879
|
}
|
|
549
|
-
debugDomains(zoneName, process.env.VERCEL_ENV, zone.production.toString());
|
|
550
|
-
return zone.production.toString();
|
|
551
880
|
}
|
|
552
881
|
|
|
553
882
|
// src/next/middleware/middleware.ts
|
|
@@ -570,197 +899,188 @@ async function verifyPreviewDomain(req, rewriteDomain) {
|
|
|
570
899
|
const vercelError = previewResponse.headers.get("x-vercel-error");
|
|
571
900
|
return !(previewResponse.status === 404 && (vercelError === "DEPLOYMENT_NOT_FOUND" || vercelError === "NOT_FOUND"));
|
|
572
901
|
}
|
|
573
|
-
function microfrontendInternalRoutingHandler({
|
|
574
|
-
config
|
|
575
|
-
}) {
|
|
576
|
-
return async (req) => {
|
|
577
|
-
const payload = Object.fromEntries(
|
|
578
|
-
await Promise.all(
|
|
579
|
-
config.getAllApplications().map(async (application) => {
|
|
580
|
-
let rewriteDomain = getDomainForCurrentEnvironment(application, {
|
|
581
|
-
ignoreOverride: true
|
|
582
|
-
});
|
|
583
|
-
const isPreviewDomainAvailable = await verifyPreviewDomain(
|
|
584
|
-
req,
|
|
585
|
-
rewriteDomain
|
|
586
|
-
);
|
|
587
|
-
if (!isPreviewDomainAvailable) {
|
|
588
|
-
rewriteDomain = application.production.toString();
|
|
589
|
-
}
|
|
590
|
-
const url = new URL(rewriteDomain);
|
|
591
|
-
return [application.name, { routing: { host: url.host } }];
|
|
592
|
-
})
|
|
593
|
-
)
|
|
594
|
-
);
|
|
595
|
-
return import_server.NextResponse.json(payload);
|
|
596
|
-
};
|
|
597
|
-
}
|
|
598
902
|
function getHandler({
|
|
903
|
+
config,
|
|
599
904
|
application,
|
|
600
905
|
flagFn,
|
|
601
|
-
pattern
|
|
906
|
+
pattern,
|
|
907
|
+
production
|
|
602
908
|
}) {
|
|
603
909
|
return async (req) => {
|
|
604
|
-
var _a, _b
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
callback
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
910
|
+
var _a, _b;
|
|
911
|
+
try {
|
|
912
|
+
const pathname = req.nextUrl.pathname;
|
|
913
|
+
const search = req.nextUrl.search;
|
|
914
|
+
const proxyRouting = req.headers.get("X-Vercel-Mfe-Proxy") === "1";
|
|
915
|
+
let rewriteDomain = proxyRouting ? null : getDomainForCurrentEnvironment(config, application.name);
|
|
916
|
+
const patchedHeaders = new Headers(req.headers);
|
|
917
|
+
const responseCallbacks = [];
|
|
918
|
+
const onRewrite = (response) => {
|
|
919
|
+
for (const callback of responseCallbacks) {
|
|
920
|
+
callback(response);
|
|
921
|
+
}
|
|
922
|
+
return response;
|
|
923
|
+
};
|
|
924
|
+
if (process.env.VERCEL_ENV === "preview" && rewriteDomain) {
|
|
925
|
+
const zoneFallbackCookieName = `__zone_${application.name}_production_fallback`;
|
|
926
|
+
const assetPrefix = application.getAssetPrefix();
|
|
927
|
+
if (assetPrefix && pathname.startsWith(`/${assetPrefix}`) && ((_a = req.cookies.get(zoneFallbackCookieName)) == null ? void 0 : _a.value) === "1") {
|
|
928
|
+
rewriteDomain = production.toString();
|
|
929
|
+
} else {
|
|
930
|
+
try {
|
|
931
|
+
let deploymentFound;
|
|
932
|
+
if (req.headers.get("x-vercel-skip-deployment-existence-check")) {
|
|
933
|
+
deploymentFound = true;
|
|
934
|
+
} else {
|
|
935
|
+
deploymentFound = await verifyPreviewDomain(req, rewriteDomain);
|
|
936
|
+
}
|
|
937
|
+
if (!deploymentFound) {
|
|
938
|
+
rewriteDomain = production.toString();
|
|
939
|
+
responseCallbacks.push((response) => {
|
|
940
|
+
response.cookies.set(zoneFallbackCookieName, "1", {
|
|
941
|
+
httpOnly: true,
|
|
942
|
+
sameSite: "lax",
|
|
943
|
+
secure: true,
|
|
944
|
+
maxAge: 60
|
|
945
|
+
// 1 minute
|
|
946
|
+
});
|
|
639
947
|
});
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
948
|
+
try {
|
|
949
|
+
const existingCookie = patchedHeaders.get("cookie");
|
|
950
|
+
if (!(existingCookie == null ? void 0 : existingCookie.includes("__vercel_toolbar"))) {
|
|
951
|
+
patchedHeaders.set(
|
|
952
|
+
"cookie",
|
|
953
|
+
[`__vercel_toolbar=1`, existingCookie].join("; ")
|
|
954
|
+
);
|
|
955
|
+
responseCallbacks.push((response) => {
|
|
956
|
+
response.cookies.set("__vercel_toolbar", "1", {
|
|
957
|
+
httpOnly: false,
|
|
958
|
+
sameSite: "lax",
|
|
959
|
+
secure: true,
|
|
960
|
+
maxAge: 29030400
|
|
961
|
+
});
|
|
654
962
|
});
|
|
655
|
-
}
|
|
963
|
+
}
|
|
964
|
+
} catch (error) {
|
|
656
965
|
}
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
maxAge: 0
|
|
966
|
+
} else if (((_b = req.cookies.get(zoneFallbackCookieName)) == null ? void 0 : _b.value) === "1") {
|
|
967
|
+
responseCallbacks.push((response) => {
|
|
968
|
+
response.cookies.set(zoneFallbackCookieName, "", {
|
|
969
|
+
httpOnly: true,
|
|
970
|
+
sameSite: "lax",
|
|
971
|
+
secure: true,
|
|
972
|
+
maxAge: 0
|
|
973
|
+
});
|
|
666
974
|
});
|
|
667
|
-
}
|
|
975
|
+
}
|
|
976
|
+
} catch {
|
|
668
977
|
}
|
|
669
|
-
} catch {
|
|
670
978
|
}
|
|
671
979
|
}
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
980
|
+
const isFlagEnabled = async () => flagFn ? flagFn() : true;
|
|
981
|
+
if (pattern.test(pathname) && await isFlagEnabled()) {
|
|
982
|
+
if (proxyRouting) {
|
|
983
|
+
const headers = new Headers(req.headers);
|
|
984
|
+
headers.set("x-vercel-mfe-zone", application.name);
|
|
985
|
+
return onRewrite(
|
|
986
|
+
import_server.NextResponse.next({
|
|
987
|
+
request: {
|
|
988
|
+
headers
|
|
989
|
+
},
|
|
990
|
+
headers: {
|
|
991
|
+
// temporary, can delete when proxyRouting flag is removed
|
|
992
|
+
"x-vercel-mfe-middleware-sent-proxy": application.name
|
|
993
|
+
}
|
|
994
|
+
})
|
|
995
|
+
);
|
|
996
|
+
}
|
|
678
997
|
return onRewrite(
|
|
679
|
-
import_server.NextResponse.
|
|
998
|
+
import_server.NextResponse.rewrite(`${rewriteDomain}${pathname}${search}`, {
|
|
680
999
|
request: {
|
|
681
|
-
headers
|
|
682
|
-
},
|
|
683
|
-
headers: {
|
|
684
|
-
// temporary, can delete when proxyRouting flag is removed
|
|
685
|
-
"x-vercel-mfe-middleware-sent-proxy": application.name
|
|
1000
|
+
headers: patchedHeaders
|
|
686
1001
|
}
|
|
687
1002
|
})
|
|
688
1003
|
);
|
|
689
1004
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
headers: patchedHeaders
|
|
694
|
-
}
|
|
695
|
-
})
|
|
696
|
-
);
|
|
1005
|
+
} catch (e) {
|
|
1006
|
+
console.error("An error occured in the microfrontends middleware:", e);
|
|
1007
|
+
throw e;
|
|
697
1008
|
}
|
|
698
1009
|
};
|
|
699
1010
|
}
|
|
700
1011
|
function getMicrofrontendsMiddleware({
|
|
701
1012
|
request,
|
|
702
|
-
flagValues
|
|
1013
|
+
flagValues,
|
|
1014
|
+
fromApp
|
|
703
1015
|
}) {
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
1016
|
+
const microfrontends = Microfrontends.fromEnv({
|
|
1017
|
+
cookies: request.cookies.getAll(),
|
|
1018
|
+
meta: {
|
|
1019
|
+
fromApp
|
|
1020
|
+
}
|
|
707
1021
|
});
|
|
708
1022
|
const middlewares = [];
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
1023
|
+
if (microfrontends.config instanceof MicrofrontendChildConfig) {
|
|
1024
|
+
return middlewares;
|
|
1025
|
+
}
|
|
1026
|
+
const config = microfrontends.config;
|
|
1027
|
+
const production = config.defaultApplication.production;
|
|
1028
|
+
for (const application of config.getChildApplications()) {
|
|
714
1029
|
if (application.name === process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION) {
|
|
715
1030
|
continue;
|
|
716
1031
|
}
|
|
717
|
-
if (
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
);
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
for (const path of pathGroup.paths) {
|
|
743
|
-
const pattern = (0, import_path_to_regexp.pathToRegexp)(path);
|
|
744
|
-
middlewares.push({
|
|
745
|
-
src: pattern,
|
|
746
|
-
fn: getHandler({
|
|
747
|
-
application,
|
|
748
|
-
flagFn,
|
|
749
|
-
pattern
|
|
750
|
-
})
|
|
751
|
-
});
|
|
1032
|
+
if (process.env.VERCEL_ENV === "preview") {
|
|
1033
|
+
const pattern = (0, import_path_to_regexp3.pathToRegexp)(`/${application.getAssetPrefix()}/:path+`);
|
|
1034
|
+
middlewares.push({
|
|
1035
|
+
src: pattern,
|
|
1036
|
+
fn: getHandler({
|
|
1037
|
+
config,
|
|
1038
|
+
application,
|
|
1039
|
+
pattern,
|
|
1040
|
+
production
|
|
1041
|
+
})
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
for (const pathGroup of application.routing) {
|
|
1045
|
+
if (process.env.VERCEL_ENV === "preview" || pathGroup.flag) {
|
|
1046
|
+
const flagName = pathGroup.flag;
|
|
1047
|
+
let flagFn;
|
|
1048
|
+
if (flagName) {
|
|
1049
|
+
flagFn = flagValues == null ? void 0 : flagValues[flagName];
|
|
1050
|
+
if (!flagFn) {
|
|
1051
|
+
throw new Error(
|
|
1052
|
+
`Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${application.name} but not found in provided flag values.`
|
|
1053
|
+
);
|
|
752
1054
|
}
|
|
753
1055
|
}
|
|
1056
|
+
for (const path of pathGroup.paths) {
|
|
1057
|
+
const pattern = (0, import_path_to_regexp3.pathToRegexp)(path);
|
|
1058
|
+
middlewares.push({
|
|
1059
|
+
src: pattern,
|
|
1060
|
+
fn: getHandler({
|
|
1061
|
+
config,
|
|
1062
|
+
application,
|
|
1063
|
+
flagFn,
|
|
1064
|
+
pattern,
|
|
1065
|
+
production
|
|
1066
|
+
})
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
754
1069
|
}
|
|
755
1070
|
}
|
|
756
1071
|
}
|
|
757
1072
|
return middlewares;
|
|
758
1073
|
}
|
|
759
|
-
async function runMicrofrontendsMiddleware(
|
|
1074
|
+
async function runMicrofrontendsMiddleware({
|
|
1075
|
+
request,
|
|
1076
|
+
fromApp,
|
|
1077
|
+
flagValues
|
|
1078
|
+
}) {
|
|
760
1079
|
const pathname = request.nextUrl.pathname;
|
|
761
1080
|
const middlewares = getMicrofrontendsMiddleware({
|
|
762
1081
|
request,
|
|
763
|
-
flagValues
|
|
1082
|
+
flagValues,
|
|
1083
|
+
fromApp
|
|
764
1084
|
});
|
|
765
1085
|
for (const mware of middlewares) {
|
|
766
1086
|
if (typeof mware.src === "string" ? pathname === mware.src : mware.src.test(pathname)) {
|