@vercel/microfrontends 0.14.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/dist/bin/cli.cjs +377 -1626
- 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/{v2/microfrontends → microfrontends}/server.cjs +63 -143
- 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 +63 -143
- package/dist/microfrontends/server.js.map +1 -0
- package/dist/{v2/microfrontends.cjs → microfrontends.cjs} +21 -21
- 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} +20 -20
- 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 +13 -2
- package/dist/next/endpoints.js +77 -18
- package/dist/next/endpoints.js.map +1 -1
- package/dist/next/middleware.cjs +745 -396
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.d.ts +10 -5
- package/dist/next/middleware.js +745 -396
- 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/{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 +211 -1333
- package/dist/utils/mfe-port.cjs.map +1 -1
- package/dist/utils/mfe-port.js +204 -1326
- 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,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;
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
|
|
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;
|
|
495
762
|
}
|
|
496
763
|
};
|
|
497
764
|
|
|
498
|
-
// src/config/
|
|
499
|
-
var
|
|
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
|
|
@@ -571,167 +900,187 @@ async function verifyPreviewDomain(req, rewriteDomain) {
|
|
|
571
900
|
return !(previewResponse.status === 404 && (vercelError === "DEPLOYMENT_NOT_FOUND" || vercelError === "NOT_FOUND"));
|
|
572
901
|
}
|
|
573
902
|
function getHandler({
|
|
903
|
+
config,
|
|
574
904
|
application,
|
|
575
905
|
flagFn,
|
|
576
|
-
pattern
|
|
906
|
+
pattern,
|
|
907
|
+
production
|
|
577
908
|
}) {
|
|
578
909
|
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
|
-
|
|
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
|
+
});
|
|
614
947
|
});
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
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
|
+
});
|
|
629
962
|
});
|
|
630
|
-
}
|
|
963
|
+
}
|
|
964
|
+
} catch (error) {
|
|
631
965
|
}
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
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
|
+
});
|
|
641
974
|
});
|
|
642
|
-
}
|
|
975
|
+
}
|
|
976
|
+
} catch {
|
|
643
977
|
}
|
|
644
|
-
} catch {
|
|
645
978
|
}
|
|
646
979
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
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
|
+
}
|
|
653
997
|
return onRewrite(
|
|
654
|
-
import_server.NextResponse.
|
|
998
|
+
import_server.NextResponse.rewrite(`${rewriteDomain}${pathname}${search}`, {
|
|
655
999
|
request: {
|
|
656
|
-
headers
|
|
657
|
-
},
|
|
658
|
-
headers: {
|
|
659
|
-
// temporary, can delete when proxyRouting flag is removed
|
|
660
|
-
"x-vercel-mfe-middleware-sent-proxy": application.name
|
|
1000
|
+
headers: patchedHeaders
|
|
661
1001
|
}
|
|
662
1002
|
})
|
|
663
1003
|
);
|
|
664
1004
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
headers: patchedHeaders
|
|
669
|
-
}
|
|
670
|
-
})
|
|
671
|
-
);
|
|
1005
|
+
} catch (e) {
|
|
1006
|
+
console.error("An error occured in the microfrontends middleware:", e);
|
|
1007
|
+
throw e;
|
|
672
1008
|
}
|
|
673
1009
|
};
|
|
674
1010
|
}
|
|
675
1011
|
function getMicrofrontendsMiddleware({
|
|
676
1012
|
request,
|
|
677
|
-
flagValues
|
|
1013
|
+
flagValues,
|
|
1014
|
+
fromApp
|
|
678
1015
|
}) {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
1016
|
+
const microfrontends = Microfrontends.fromEnv({
|
|
1017
|
+
cookies: request.cookies.getAll(),
|
|
1018
|
+
meta: {
|
|
1019
|
+
fromApp
|
|
1020
|
+
}
|
|
682
1021
|
});
|
|
683
1022
|
const middlewares = [];
|
|
684
|
-
|
|
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()) {
|
|
685
1029
|
if (application.name === process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION) {
|
|
686
1030
|
continue;
|
|
687
1031
|
}
|
|
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
|
-
});
|
|
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
|
+
);
|
|
723
1054
|
}
|
|
724
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
|
+
}
|
|
725
1069
|
}
|
|
726
1070
|
}
|
|
727
1071
|
}
|
|
728
1072
|
return middlewares;
|
|
729
1073
|
}
|
|
730
|
-
async function runMicrofrontendsMiddleware(
|
|
1074
|
+
async function runMicrofrontendsMiddleware({
|
|
1075
|
+
request,
|
|
1076
|
+
fromApp,
|
|
1077
|
+
flagValues
|
|
1078
|
+
}) {
|
|
731
1079
|
const pathname = request.nextUrl.pathname;
|
|
732
1080
|
const middlewares = getMicrofrontendsMiddleware({
|
|
733
1081
|
request,
|
|
734
|
-
flagValues
|
|
1082
|
+
flagValues,
|
|
1083
|
+
fromApp
|
|
735
1084
|
});
|
|
736
1085
|
for (const mware of middlewares) {
|
|
737
1086
|
if (typeof mware.src === "string" ? pathname === mware.src : mware.src.test(pathname)) {
|