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