@vercel/microfrontends 0.14.0 → 0.16.0

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