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