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