@vercel/microfrontends 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.cjs +377 -1626
- package/dist/config.cjs +460 -1004
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.ts +4 -25
- package/dist/config.js +456 -983
- package/dist/config.js.map +1 -1
- package/dist/{v2/microfrontends → microfrontends}/server.cjs +63 -143
- package/dist/microfrontends/server.cjs.map +1 -0
- package/dist/{v2/microfrontends → microfrontends}/server.d.ts +4 -4
- package/dist/{v2/microfrontends → microfrontends}/server.js +63 -143
- package/dist/microfrontends/server.js.map +1 -0
- package/dist/{v2/microfrontends.cjs → microfrontends.cjs} +21 -21
- package/dist/microfrontends.cjs.map +1 -0
- package/dist/{v2/microfrontends.d.ts → microfrontends.d.ts} +4 -4
- package/dist/{v2/microfrontends.js → microfrontends.js} +20 -20
- package/dist/microfrontends.js.map +1 -0
- package/dist/next/client.cjs +1 -1
- package/dist/next/client.cjs.map +1 -1
- package/dist/next/client.js +1 -1
- package/dist/next/client.js.map +1 -1
- package/dist/next/config.cjs +1323 -1024
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.d.ts +1 -1
- package/dist/next/config.js +1327 -1028
- package/dist/next/config.js.map +1 -1
- package/dist/next/endpoints.cjs +77 -18
- package/dist/next/endpoints.cjs.map +1 -1
- package/dist/next/endpoints.d.ts +13 -2
- package/dist/next/endpoints.js +77 -18
- package/dist/next/endpoints.js.map +1 -1
- package/dist/next/middleware.cjs +745 -396
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.d.ts +10 -5
- package/dist/next/middleware.js +745 -396
- package/dist/next/middleware.js.map +1 -1
- package/dist/next/testing.cjs +595 -1032
- package/dist/next/testing.cjs.map +1 -1
- package/dist/next/testing.d.ts +14 -12
- package/dist/next/testing.js +589 -1016
- package/dist/next/testing.js.map +1 -1
- package/dist/overrides.cjs +40 -108
- package/dist/overrides.cjs.map +1 -1
- package/dist/overrides.d.ts +24 -2
- package/dist/overrides.js +36 -106
- package/dist/overrides.js.map +1 -1
- package/dist/{v2/routing.cjs → routing.cjs} +3 -3
- package/dist/routing.cjs.map +1 -0
- package/dist/{v2/schema.cjs → schema.cjs} +1 -1
- package/dist/schema.cjs.map +1 -0
- package/dist/schema.d.ts +1 -0
- package/dist/utils/mfe-port.cjs +211 -1333
- package/dist/utils/mfe-port.cjs.map +1 -1
- package/dist/utils/mfe-port.js +204 -1326
- package/dist/utils/mfe-port.js.map +1 -1
- package/dist/validation.cjs +31 -361
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.d.ts +3 -146
- package/dist/validation.js +30 -359
- package/dist/validation.js.map +1 -1
- package/package.json +29 -92
- package/schema/schema.json +174 -244
- package/dist/config/client.cjs +0 -54
- package/dist/config/client.cjs.map +0 -1
- package/dist/config/client.d.ts +0 -23
- package/dist/config/client.js +0 -28
- package/dist/config/client.js.map +0 -1
- package/dist/config/edge.cjs +0 -508
- package/dist/config/edge.cjs.map +0 -1
- package/dist/config/edge.d.ts +0 -20
- package/dist/config/edge.js +0 -481
- package/dist/config/edge.js.map +0 -1
- package/dist/microfrontend-config-983a5139.d.ts +0 -154
- package/dist/schema-2922d49e.d.ts +0 -182
- package/dist/v2/config.cjs +0 -709
- package/dist/v2/config.cjs.map +0 -1
- package/dist/v2/config.d.ts +0 -4
- package/dist/v2/config.js +0 -684
- package/dist/v2/config.js.map +0 -1
- package/dist/v2/microfrontends/server.cjs.map +0 -1
- package/dist/v2/microfrontends/server.js.map +0 -1
- package/dist/v2/microfrontends.cjs.map +0 -1
- package/dist/v2/microfrontends.js.map +0 -1
- package/dist/v2/next/client.cjs +0 -3
- package/dist/v2/next/client.cjs.map +0 -1
- package/dist/v2/next/client.d.ts +0 -45
- package/dist/v2/next/client.js +0 -3
- package/dist/v2/next/client.js.map +0 -1
- package/dist/v2/next/config.cjs +0 -2178
- package/dist/v2/next/config.cjs.map +0 -1
- package/dist/v2/next/config.d.ts +0 -22
- package/dist/v2/next/config.js +0 -2143
- package/dist/v2/next/config.js.map +0 -1
- package/dist/v2/next/endpoints.cjs +0 -141
- package/dist/v2/next/endpoints.cjs.map +0 -1
- package/dist/v2/next/endpoints.d.ts +0 -26
- package/dist/v2/next/endpoints.js +0 -116
- package/dist/v2/next/endpoints.js.map +0 -1
- package/dist/v2/next/middleware.cjs +0 -1099
- package/dist/v2/next/middleware.cjs.map +0 -1
- package/dist/v2/next/middleware.d.ts +0 -34
- package/dist/v2/next/middleware.js +0 -1071
- package/dist/v2/next/middleware.js.map +0 -1
- package/dist/v2/next/testing.cjs +0 -992
- package/dist/v2/next/testing.cjs.map +0 -1
- package/dist/v2/next/testing.d.ts +0 -55
- package/dist/v2/next/testing.js +0 -961
- package/dist/v2/next/testing.js.map +0 -1
- package/dist/v2/overrides.cjs +0 -75
- package/dist/v2/overrides.cjs.map +0 -1
- package/dist/v2/overrides.d.ts +0 -24
- package/dist/v2/overrides.js +0 -45
- package/dist/v2/overrides.js.map +0 -1
- package/dist/v2/routing.cjs.map +0 -1
- package/dist/v2/schema.cjs.map +0 -1
- package/dist/v2/schema.d.ts +0 -1
- package/schema/schema-v2.json +0 -266
- /package/dist/{v2/routing.d.ts → routing.d.ts} +0 -0
- /package/dist/{v2/routing.js → routing.js} +0 -0
- /package/dist/{v2/routing.js.map → routing.js.map} +0 -0
- /package/dist/{v2/schema.js → schema.js} +0 -0
- /package/dist/{v2/schema.js.map → schema.js.map} +0 -0
package/dist/next/config.js
CHANGED
|
@@ -1,31 +1,42 @@
|
|
|
1
1
|
// src/next/config/index.ts
|
|
2
|
-
import
|
|
2
|
+
import fs6 from "node:fs";
|
|
3
3
|
|
|
4
|
-
// src/config/
|
|
5
|
-
import
|
|
4
|
+
// src/config/microfrontends/server/index.ts
|
|
5
|
+
import fs5 from "node:fs";
|
|
6
|
+
import { dirname as dirname3, join as join2 } from "node:path";
|
|
6
7
|
|
|
7
|
-
// src/config
|
|
8
|
-
|
|
8
|
+
// src/config/overrides/constants.ts
|
|
9
|
+
var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
|
|
10
|
+
var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
9
11
|
|
|
10
|
-
// src/config
|
|
11
|
-
|
|
12
|
-
var
|
|
12
|
+
// src/config/overrides/is-override-cookie.ts
|
|
13
|
+
function isOverrideCookie(cookie) {
|
|
14
|
+
var _a;
|
|
15
|
+
return Boolean((_a = cookie.name) == null ? void 0 : _a.startsWith(OVERRIDES_COOKIE_PREFIX));
|
|
16
|
+
}
|
|
13
17
|
|
|
14
|
-
// src/
|
|
15
|
-
function
|
|
16
|
-
|
|
18
|
+
// src/config/overrides/get-override-from-cookie.ts
|
|
19
|
+
function getOverrideFromCookie(cookie) {
|
|
20
|
+
if (!isOverrideCookie(cookie) || !cookie.value)
|
|
21
|
+
return;
|
|
22
|
+
return {
|
|
23
|
+
application: cookie.name.replace(OVERRIDES_ENV_COOKIE_PREFIX, ""),
|
|
24
|
+
host: cookie.value
|
|
25
|
+
};
|
|
17
26
|
}
|
|
18
27
|
|
|
19
|
-
// src/config
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
// src/config/overrides/parse-overrides.ts
|
|
29
|
+
function parseOverrides(cookies) {
|
|
30
|
+
const overridesConfig = { applications: {} };
|
|
31
|
+
cookies.forEach((cookie) => {
|
|
32
|
+
const override = getOverrideFromCookie(cookie);
|
|
33
|
+
if (!override)
|
|
34
|
+
return;
|
|
35
|
+
overridesConfig.applications[override.application] = {
|
|
36
|
+
environment: { host: override.host }
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
return overridesConfig;
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
// src/config/errors.ts
|
|
@@ -120,131 +131,268 @@ var MicrofrontendError = class extends Error {
|
|
|
120
131
|
}
|
|
121
132
|
};
|
|
122
133
|
|
|
123
|
-
// src/
|
|
124
|
-
function
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
134
|
+
// src/config/microfrontends-config/utils/get-config-from-env.ts
|
|
135
|
+
function getConfigStringFromEnv() {
|
|
136
|
+
const config = process.env.MFE_CONFIG;
|
|
137
|
+
if (!config) {
|
|
138
|
+
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
139
|
+
type: "config",
|
|
140
|
+
subtype: "not_found_in_env"
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return config;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/config/microfrontends-config/isomorphic/index.ts
|
|
147
|
+
import { parse } from "jsonc-parser";
|
|
148
|
+
|
|
149
|
+
// src/config/schema/utils/is-main-config.ts
|
|
150
|
+
function isMainConfig(c) {
|
|
151
|
+
return !("partOf" in c);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/config/schema/utils/is-default-app.ts
|
|
155
|
+
function isDefaultApp(a) {
|
|
156
|
+
return !("routing" in a);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/config/microfrontends-config/client/index.ts
|
|
160
|
+
import { pathToRegexp } from "path-to-regexp";
|
|
161
|
+
var MicrofrontendConfigClient = class {
|
|
162
|
+
constructor(config, opts) {
|
|
163
|
+
this.pathCache = {};
|
|
164
|
+
this.serialized = config;
|
|
165
|
+
if (opts == null ? void 0 : opts.removeFlaggedPaths) {
|
|
166
|
+
for (const app of Object.values(config.applications)) {
|
|
167
|
+
if (app.routing) {
|
|
168
|
+
app.routing = app.routing.filter((match) => !match.flag);
|
|
169
|
+
}
|
|
139
170
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
171
|
+
}
|
|
172
|
+
this.applications = config.applications;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Create a new `MicrofrontendConfigClient` from a JSON string.
|
|
176
|
+
* Config must be passed in to remain framework agnostic
|
|
177
|
+
*/
|
|
178
|
+
static fromEnv(config, opts) {
|
|
179
|
+
if (!config) {
|
|
180
|
+
throw new Error("No microfrontends configuration found");
|
|
181
|
+
}
|
|
182
|
+
return new MicrofrontendConfigClient(
|
|
183
|
+
JSON.parse(config),
|
|
184
|
+
opts
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
isEqual(other) {
|
|
188
|
+
return JSON.stringify(this.applications) === JSON.stringify(other.applications);
|
|
189
|
+
}
|
|
190
|
+
getApplicationNameForPath(path5) {
|
|
191
|
+
if (!path5.startsWith("/")) {
|
|
192
|
+
throw new Error(`Path must start with a /`);
|
|
193
|
+
}
|
|
194
|
+
if (this.pathCache[path5]) {
|
|
195
|
+
return this.pathCache[path5];
|
|
196
|
+
}
|
|
197
|
+
const pathname = new URL(path5, "https://example.com").pathname;
|
|
198
|
+
for (const [name, application] of Object.entries(this.applications)) {
|
|
199
|
+
if (application.routing) {
|
|
200
|
+
for (const group of application.routing) {
|
|
201
|
+
for (const childPath of group.paths) {
|
|
202
|
+
const regexp = pathToRegexp(childPath);
|
|
203
|
+
if (regexp.test(pathname)) {
|
|
204
|
+
this.pathCache[path5] = name;
|
|
205
|
+
return name;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
146
208
|
}
|
|
147
209
|
}
|
|
148
|
-
tag = args.join(options.joinString);
|
|
149
|
-
tag = tag.replace(/\s/g, options.joinString);
|
|
150
|
-
if (options.lowercaseOnly)
|
|
151
|
-
tag = tag.toLowerCase();
|
|
152
|
-
tag = tag.replace(options.regexRemovePattern, (match) => {
|
|
153
|
-
if (match === options.joinString)
|
|
154
|
-
return match;
|
|
155
|
-
return "";
|
|
156
|
-
});
|
|
157
|
-
if (tag.length > options.maxLen)
|
|
158
|
-
tag = tag.substring(0, options.maxLen);
|
|
159
|
-
tag = tag.replace(reJoinString, options.joinString);
|
|
160
|
-
return tag;
|
|
161
210
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
|
|
171
|
-
var _Overrides = class {
|
|
172
|
-
constructor(config) {
|
|
173
|
-
this.config = config;
|
|
211
|
+
const defaultApplication = Object.entries(this.applications).find(
|
|
212
|
+
([, application]) => application.default
|
|
213
|
+
);
|
|
214
|
+
if (!defaultApplication) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
this.pathCache[path5] = defaultApplication[0];
|
|
218
|
+
return defaultApplication[0];
|
|
174
219
|
}
|
|
175
|
-
|
|
176
|
-
return
|
|
220
|
+
serialize() {
|
|
221
|
+
return this.serialized;
|
|
177
222
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// src/config/microfrontends-config/isomorphic/validation.ts
|
|
226
|
+
import { pathToRegexp as pathToRegexp2, parse as parsePathRegexp } from "path-to-regexp";
|
|
227
|
+
var SUPPORTED_VERSIONS = ["2"];
|
|
228
|
+
var validateConfigVersion = (version) => {
|
|
229
|
+
if (!SUPPORTED_VERSIONS.includes(version)) {
|
|
230
|
+
throw new MicrofrontendError(
|
|
231
|
+
`Unsupported version: ${version}. Supported versions are: ${SUPPORTED_VERSIONS.join(
|
|
232
|
+
", "
|
|
233
|
+
)}`,
|
|
234
|
+
{ type: "config", subtype: "unsupported_version" }
|
|
235
|
+
);
|
|
181
236
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
return
|
|
186
|
-
zone: cookie.name.replace(_Overrides.overrideEnvCookiePrefix, ""),
|
|
187
|
-
host: cookie.value
|
|
188
|
-
};
|
|
237
|
+
};
|
|
238
|
+
var validateConfigPaths = (applicationConfigsById) => {
|
|
239
|
+
if (!applicationConfigsById) {
|
|
240
|
+
return;
|
|
189
241
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
242
|
+
const pathsByApplicationId = /* @__PURE__ */ new Map();
|
|
243
|
+
const errors = [];
|
|
244
|
+
for (const [id, app] of Object.entries(applicationConfigsById)) {
|
|
245
|
+
if (isDefaultApp(app)) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
for (const pathMatch of app.routing) {
|
|
249
|
+
for (const path5 of pathMatch.paths) {
|
|
250
|
+
const tokens = parsePathRegexp(path5);
|
|
251
|
+
for (const token of tokens.slice(0, -1)) {
|
|
252
|
+
if (typeof token !== "string") {
|
|
253
|
+
errors.push(
|
|
254
|
+
`Path ${path5} may only have a :wildcard in the last path component`
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const existing = pathsByApplicationId.get(path5);
|
|
259
|
+
if (existing) {
|
|
260
|
+
existing.applications.push(id);
|
|
261
|
+
} else {
|
|
262
|
+
pathsByApplicationId.set(path5, {
|
|
263
|
+
applications: [id],
|
|
264
|
+
matcher: pathToRegexp2(path5),
|
|
265
|
+
applicationId: id
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
201
270
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
271
|
+
const entries = Array.from(pathsByApplicationId.entries());
|
|
272
|
+
entries.forEach(([path5, { applications: ids, matcher, applicationId }]) => {
|
|
273
|
+
if (ids.length > 1) {
|
|
274
|
+
errors.push(
|
|
275
|
+
`Duplicate path "${path5}" for applications "${ids.join(", ")}"`
|
|
276
|
+
);
|
|
207
277
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
278
|
+
entries.forEach(
|
|
279
|
+
([
|
|
280
|
+
matchPath,
|
|
281
|
+
{ applications: matchIds, applicationId: matchApplicationId }
|
|
282
|
+
]) => {
|
|
283
|
+
if (path5 === matchPath) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (applicationId === matchApplicationId) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (matcher.test(matchPath)) {
|
|
290
|
+
const source = `"${path5}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
291
|
+
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
292
|
+
errors.push(
|
|
293
|
+
`Overlapping path detected between ${source} and ${destination}`
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
);
|
|
298
|
+
});
|
|
299
|
+
if (errors.length) {
|
|
300
|
+
throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
|
|
301
|
+
type: "config",
|
|
302
|
+
subtype: "conflicting_paths"
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
var validateAppPaths = (name, app) => {
|
|
307
|
+
for (const group of app.routing) {
|
|
308
|
+
for (const p of group.paths) {
|
|
309
|
+
if (p === "/") {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (p.endsWith("/")) {
|
|
313
|
+
throw new MicrofrontendError(
|
|
314
|
+
`Invalid path for application "${name}". ${p} must not end with a slash.`,
|
|
315
|
+
{ type: "application", subtype: "invalid_path" }
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
if (!p.startsWith("/")) {
|
|
319
|
+
throw new MicrofrontendError(
|
|
320
|
+
`Invalid path for application "${name}". ${p} must start with a slash.`,
|
|
321
|
+
{ type: "application", subtype: "invalid_path" }
|
|
322
|
+
);
|
|
323
|
+
}
|
|
213
324
|
}
|
|
214
|
-
const suffix = previewDeploymentSuffix ? `.${previewDeploymentSuffix}` : `-${teamSlug}.vercel.app`;
|
|
215
|
-
return [
|
|
216
|
-
`${parsedProjectName}-git-([a-zA-Z0-9-]+)${suffix}`,
|
|
217
|
-
microfrontendConfig.getZone(zone).production.host
|
|
218
|
-
];
|
|
219
325
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
)}$`
|
|
225
|
-
).test(domain);
|
|
326
|
+
};
|
|
327
|
+
var validateConfigDefaultApplication = (applicationConfigsById) => {
|
|
328
|
+
if (!applicationConfigsById) {
|
|
329
|
+
return;
|
|
226
330
|
}
|
|
227
|
-
|
|
228
|
-
|
|
331
|
+
const applicationsWithRouting = Object.entries(applicationConfigsById).filter(
|
|
332
|
+
([, app]) => !isDefaultApp(app)
|
|
333
|
+
);
|
|
334
|
+
const applicationsWithRoutingNames = applicationsWithRouting.map(
|
|
335
|
+
([key]) => key
|
|
336
|
+
);
|
|
337
|
+
const numApplications = Object.keys(applicationConfigsById).length;
|
|
338
|
+
const numApplicationsWithRouting = applicationsWithRoutingNames.length;
|
|
339
|
+
const numApplicationsWithoutRouting = numApplications - numApplicationsWithRouting;
|
|
340
|
+
if (numApplicationsWithoutRouting === 0) {
|
|
341
|
+
throw new MicrofrontendError(
|
|
342
|
+
`No default application found. At least one application needs to be the default by omitting routing.`,
|
|
343
|
+
{ type: "config", subtype: "no_default_application" }
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
if (numApplicationsWithoutRouting > 1) {
|
|
347
|
+
throw new MicrofrontendError(
|
|
348
|
+
`Only one application can omit "routing". Found ${applicationsWithRoutingNames.length - Object.keys(applicationConfigsById).length > 1}.`,
|
|
349
|
+
{ type: "config", subtype: "multiple_default_applications" }
|
|
350
|
+
);
|
|
229
351
|
}
|
|
230
352
|
};
|
|
231
|
-
var Overrides = _Overrides;
|
|
232
|
-
Overrides.overrideEnvCookiePrefix = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
233
353
|
|
|
234
|
-
// src/config/
|
|
354
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
|
|
355
|
+
var PREFIX = "vc-ap";
|
|
356
|
+
function generateAssetPrefixFromName({
|
|
357
|
+
name
|
|
358
|
+
}) {
|
|
359
|
+
if (!name) {
|
|
360
|
+
throw new Error("Name is required to generate an asset prefix");
|
|
361
|
+
}
|
|
362
|
+
return `${PREFIX}-${name}`;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-port.ts
|
|
366
|
+
function generatePortFromName({
|
|
367
|
+
name,
|
|
368
|
+
minPort = 3e3,
|
|
369
|
+
maxPort = 8e3
|
|
370
|
+
}) {
|
|
371
|
+
if (!name) {
|
|
372
|
+
throw new Error("Name is required to generate a port");
|
|
373
|
+
}
|
|
374
|
+
let hash = 0;
|
|
375
|
+
for (let i = 0; i < name.length; i++) {
|
|
376
|
+
hash = (hash << 5) - hash + name.charCodeAt(i);
|
|
377
|
+
hash |= 0;
|
|
378
|
+
}
|
|
379
|
+
hash = Math.abs(hash);
|
|
380
|
+
const range = maxPort - minPort;
|
|
381
|
+
const port = minPort + hash % range;
|
|
382
|
+
return port;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// src/config/microfrontends-config/isomorphic/host.ts
|
|
235
386
|
var Host = class {
|
|
236
|
-
constructor(
|
|
237
|
-
|
|
387
|
+
constructor(hostConfig, options) {
|
|
388
|
+
const { protocol = "https", host, port } = hostConfig;
|
|
389
|
+
this.protocol = protocol;
|
|
238
390
|
this.host = host;
|
|
239
391
|
this.port = Host.getPort({ port, protocol: this.protocol });
|
|
240
|
-
this.
|
|
241
|
-
protocol,
|
|
242
|
-
host,
|
|
243
|
-
...port ? { port } : void 0
|
|
244
|
-
};
|
|
392
|
+
this.local = options == null ? void 0 : options.isLocal;
|
|
245
393
|
}
|
|
246
394
|
isLocal() {
|
|
247
|
-
return this.host === "localhost" || this.host === "127.0.0.1";
|
|
395
|
+
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
248
396
|
}
|
|
249
397
|
static getPort({
|
|
250
398
|
protocol,
|
|
@@ -270,176 +418,234 @@ var Host = class {
|
|
|
270
418
|
const url = `${this.protocol}://${this.host}${this.isDefaultPort() && !includeDefaultPort ? "" : `:${this.port}`}`;
|
|
271
419
|
return new URL(url);
|
|
272
420
|
}
|
|
273
|
-
|
|
274
|
-
|
|
421
|
+
};
|
|
422
|
+
var LocalHost = class extends Host {
|
|
423
|
+
constructor({
|
|
424
|
+
appName,
|
|
425
|
+
...hostConfig
|
|
426
|
+
}) {
|
|
427
|
+
const host = hostConfig.host ?? "localhost";
|
|
428
|
+
const port = hostConfig.port ?? generatePortFromName({ name: appName });
|
|
429
|
+
const protocol = hostConfig.protocol ?? "http";
|
|
430
|
+
super({ protocol, host, port });
|
|
275
431
|
}
|
|
276
432
|
};
|
|
277
433
|
|
|
278
|
-
// src/config/
|
|
434
|
+
// src/config/microfrontends-config/isomorphic/application.ts
|
|
279
435
|
var Application = class {
|
|
280
436
|
constructor(name, {
|
|
281
437
|
app,
|
|
282
|
-
overrides
|
|
438
|
+
overrides,
|
|
439
|
+
isDefault
|
|
283
440
|
}) {
|
|
284
|
-
|
|
441
|
+
var _a, _b;
|
|
285
442
|
this.name = name;
|
|
286
|
-
this.default = app.default;
|
|
287
|
-
this.routing = app.routing;
|
|
288
443
|
this.development = {
|
|
289
|
-
local: new
|
|
290
|
-
|
|
444
|
+
local: new LocalHost({
|
|
445
|
+
appName: name,
|
|
446
|
+
...(_a = app.development) == null ? void 0 : _a.local
|
|
447
|
+
}),
|
|
448
|
+
fallback: ((_b = app.development) == null ? void 0 : _b.fallback) ? new Host(app.development.fallback) : void 0
|
|
291
449
|
};
|
|
292
|
-
this.production = new Host(app.production);
|
|
450
|
+
this.production = app.production ? new Host(app.production) : void 0;
|
|
293
451
|
this.vercel = app.vercel;
|
|
294
452
|
this.overrides = (overrides == null ? void 0 : overrides.environment) ? {
|
|
295
453
|
environment: new Host(overrides.environment)
|
|
296
454
|
} : void 0;
|
|
455
|
+
this.default = isDefault ?? false;
|
|
456
|
+
this.serialized = app;
|
|
297
457
|
}
|
|
298
458
|
isDefault() {
|
|
299
459
|
return this.default;
|
|
300
460
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
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("/"))) {
|
|
304
|
-
throw new MicrofrontendError(
|
|
305
|
-
`Invalid assetPrefix for application "${name}". Must not start or end with a slash.`,
|
|
306
|
-
{ type: "zone", subtype: "invalid_asset_prefix" }
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
for (const group of ((_e = app.routing) == null ? void 0 : _e.matches) ?? []) {
|
|
310
|
-
for (const p of group.paths) {
|
|
311
|
-
if (p === "/") {
|
|
312
|
-
continue;
|
|
313
|
-
}
|
|
314
|
-
if (p.endsWith("/")) {
|
|
315
|
-
throw new MicrofrontendError(
|
|
316
|
-
`Invalid path for application "${name}". ${p} must not end with a slash.`,
|
|
317
|
-
{ type: "zone", subtype: "invalid_path" }
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
if (!p.startsWith("/")) {
|
|
321
|
-
throw new MicrofrontendError(
|
|
322
|
-
`Invalid path for application "${name}". ${p} must start with a slash.`,
|
|
323
|
-
{ type: "zone", subtype: "invalid_path" }
|
|
324
|
-
);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
461
|
+
getAssetPrefix() {
|
|
462
|
+
return generateAssetPrefixFromName({ name: this.name });
|
|
328
463
|
}
|
|
329
464
|
serialize() {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
465
|
+
return this.serialized;
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
var DefaultApplication = class extends Application {
|
|
469
|
+
constructor(name, {
|
|
470
|
+
app,
|
|
471
|
+
overrides
|
|
472
|
+
}) {
|
|
473
|
+
super(name, {
|
|
474
|
+
app,
|
|
475
|
+
overrides,
|
|
476
|
+
isDefault: true
|
|
477
|
+
});
|
|
478
|
+
this.default = true;
|
|
479
|
+
this.production = new Host(app.production);
|
|
480
|
+
}
|
|
481
|
+
getAssetPrefix() {
|
|
482
|
+
return "";
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
var ChildApplication = class extends Application {
|
|
486
|
+
constructor(name, {
|
|
487
|
+
app,
|
|
488
|
+
overrides
|
|
489
|
+
}) {
|
|
490
|
+
ChildApplication.validate(name, app);
|
|
491
|
+
super(name, {
|
|
492
|
+
app,
|
|
493
|
+
overrides,
|
|
494
|
+
isDefault: false
|
|
495
|
+
});
|
|
496
|
+
this.default = false;
|
|
497
|
+
this.routing = app.routing;
|
|
498
|
+
}
|
|
499
|
+
static validate(name, app) {
|
|
500
|
+
validateAppPaths(name, app);
|
|
352
501
|
}
|
|
353
502
|
};
|
|
354
503
|
|
|
355
|
-
// src/config/
|
|
356
|
-
var SUPPORTED_VERSIONS = ["1"];
|
|
504
|
+
// src/config/microfrontends-config/isomorphic/constants.ts
|
|
357
505
|
var DEFAULT_LOCAL_PROXY_PORT = 3024;
|
|
358
|
-
|
|
506
|
+
|
|
507
|
+
// src/config/microfrontends-config/isomorphic/index.ts
|
|
508
|
+
var MicrofrontendConfigIsomorphic = class {
|
|
359
509
|
constructor({
|
|
360
510
|
config,
|
|
361
|
-
overrides
|
|
511
|
+
overrides,
|
|
512
|
+
meta
|
|
362
513
|
}) {
|
|
363
|
-
this.
|
|
364
|
-
var _a, _b, _c;
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
514
|
+
this.childApplications = {};
|
|
515
|
+
var _a, _b, _c, _d;
|
|
516
|
+
MicrofrontendConfigIsomorphic.validate(config);
|
|
517
|
+
const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
518
|
+
this.overrides = overrides && !disableOverrides ? overrides : void 0;
|
|
519
|
+
this.isMainConfig = isMainConfig(config);
|
|
520
|
+
if (isMainConfig(config)) {
|
|
521
|
+
for (const [appId, appConfig] of Object.entries(config.applications)) {
|
|
522
|
+
const appOverrides = !disableOverrides ? (_c = this.overrides) == null ? void 0 : _c.applications[appId] : void 0;
|
|
523
|
+
if (isDefaultApp(appConfig)) {
|
|
524
|
+
this.defaultApplication = new DefaultApplication(appId, {
|
|
525
|
+
app: appConfig,
|
|
526
|
+
overrides: appOverrides
|
|
527
|
+
});
|
|
528
|
+
} else {
|
|
529
|
+
this.childApplications[appId] = new ChildApplication(appId, {
|
|
530
|
+
app: appConfig,
|
|
531
|
+
overrides: appOverrides
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
} else {
|
|
536
|
+
this.partOf = config.partOf;
|
|
537
|
+
const appOverrides = !disableOverrides ? (_d = this.overrides) == null ? void 0 : _d.applications[meta.fromApp] : void 0;
|
|
538
|
+
this.childApplications[meta.fromApp] = new ChildApplication(
|
|
539
|
+
meta.fromApp,
|
|
540
|
+
{
|
|
541
|
+
// we don't know routing because we're not in the main config
|
|
542
|
+
app: { routing: [] },
|
|
543
|
+
overrides: appOverrides
|
|
544
|
+
}
|
|
371
545
|
);
|
|
372
546
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
547
|
+
if (isMainConfig(config) && !this.defaultApplication) {
|
|
548
|
+
throw new MicrofrontendError(
|
|
549
|
+
`Could not find default application in microfrontends configuration`,
|
|
550
|
+
{
|
|
551
|
+
type: "application",
|
|
552
|
+
subtype: "not_found"
|
|
553
|
+
}
|
|
554
|
+
);
|
|
380
555
|
}
|
|
381
556
|
this.config = config;
|
|
382
|
-
this.name = config.name;
|
|
383
|
-
this.version = config.version;
|
|
384
557
|
this.options = config.options;
|
|
385
|
-
this
|
|
558
|
+
this.serialized = {
|
|
559
|
+
config,
|
|
560
|
+
overrides,
|
|
561
|
+
meta
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
static validate(config) {
|
|
565
|
+
const c = typeof config === "string" ? parse(config) : config;
|
|
566
|
+
if (isMainConfig(c)) {
|
|
567
|
+
validateConfigVersion(c.version);
|
|
568
|
+
validateConfigPaths(c.applications);
|
|
569
|
+
validateConfigDefaultApplication(c.applications);
|
|
570
|
+
}
|
|
571
|
+
return c;
|
|
572
|
+
}
|
|
573
|
+
static fromEnv({
|
|
574
|
+
meta,
|
|
575
|
+
cookies
|
|
576
|
+
}) {
|
|
577
|
+
return new MicrofrontendConfigIsomorphic({
|
|
578
|
+
config: parse(getConfigStringFromEnv()),
|
|
579
|
+
overrides: parseOverrides(cookies ?? []),
|
|
580
|
+
meta
|
|
581
|
+
});
|
|
386
582
|
}
|
|
387
583
|
isOverridesDisabled() {
|
|
388
584
|
var _a, _b;
|
|
389
585
|
return ((_b = (_a = this.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
390
586
|
}
|
|
391
|
-
static getConfigFromEnv() {
|
|
392
|
-
const config = process.env.MFE_CONFIG;
|
|
393
|
-
if (!config) {
|
|
394
|
-
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
395
|
-
type: "config",
|
|
396
|
-
subtype: "not_found_in_env"
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
return config;
|
|
400
|
-
}
|
|
401
|
-
static fromEnv(_) {
|
|
402
|
-
throw new Error("Not implemented");
|
|
403
|
-
}
|
|
404
587
|
getConfig() {
|
|
405
588
|
return this.config;
|
|
406
589
|
}
|
|
590
|
+
getApplicationsByType() {
|
|
591
|
+
return {
|
|
592
|
+
defaultApplication: this.defaultApplication,
|
|
593
|
+
applications: Object.values(this.childApplications)
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
getChildApplications() {
|
|
597
|
+
return Object.values(this.childApplications);
|
|
598
|
+
}
|
|
407
599
|
getAllApplications() {
|
|
408
|
-
return
|
|
600
|
+
return [
|
|
601
|
+
this.defaultApplication,
|
|
602
|
+
...Object.values(this.childApplications)
|
|
603
|
+
].filter(Boolean);
|
|
409
604
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
if (
|
|
605
|
+
getApplication(name) {
|
|
606
|
+
var _a;
|
|
607
|
+
if (((_a = this.defaultApplication) == null ? void 0 : _a.name) === name) {
|
|
608
|
+
return this.defaultApplication;
|
|
609
|
+
}
|
|
610
|
+
const app = this.childApplications[name];
|
|
611
|
+
if (!app) {
|
|
413
612
|
throw new MicrofrontendError(
|
|
414
613
|
`Could not find microfrontends configuration for application "${name}"`,
|
|
415
614
|
{
|
|
416
|
-
type: "
|
|
615
|
+
type: "application",
|
|
417
616
|
subtype: "not_found"
|
|
418
617
|
}
|
|
419
618
|
);
|
|
420
619
|
}
|
|
421
|
-
return
|
|
620
|
+
return app;
|
|
422
621
|
}
|
|
423
622
|
getApplicationByProjectId(projectId) {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
623
|
+
var _a, _b;
|
|
624
|
+
if (((_b = (_a = this.defaultApplication) == null ? void 0 : _a.vercel) == null ? void 0 : _b.projectId) === projectId) {
|
|
625
|
+
return this.defaultApplication;
|
|
626
|
+
}
|
|
627
|
+
return Object.values(this.childApplications).find(
|
|
628
|
+
(app) => {
|
|
629
|
+
var _a2;
|
|
630
|
+
return ((_a2 = app.vercel) == null ? void 0 : _a2.projectId) === projectId;
|
|
428
631
|
}
|
|
429
632
|
);
|
|
430
633
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
634
|
+
/**
|
|
635
|
+
* Returns the default application. This can throw if the default application
|
|
636
|
+
* is undefined ( )
|
|
637
|
+
*/
|
|
638
|
+
getDefaultApplication() {
|
|
639
|
+
if (!this.defaultApplication) {
|
|
434
640
|
throw new MicrofrontendError(
|
|
435
|
-
`Could not find default
|
|
641
|
+
`Could not find default application in microfrontends configuration`,
|
|
436
642
|
{
|
|
437
|
-
type: "
|
|
643
|
+
type: "application",
|
|
438
644
|
subtype: "not_found"
|
|
439
645
|
}
|
|
440
646
|
);
|
|
441
647
|
}
|
|
442
|
-
return
|
|
648
|
+
return this.defaultApplication;
|
|
443
649
|
}
|
|
444
650
|
/**
|
|
445
651
|
* Returns the configured port for the local proxy
|
|
@@ -454,671 +660,801 @@ var MicrofrontendConfigCommon = class {
|
|
|
454
660
|
* NOTE: This is used when writing the config to disk and must always match the input Schema
|
|
455
661
|
*/
|
|
456
662
|
toSchemaJson() {
|
|
457
|
-
|
|
458
|
-
for (const [name, zone] of Object.entries(this.zones)) {
|
|
459
|
-
applications[name] = zone.serialize();
|
|
460
|
-
}
|
|
461
|
-
return {
|
|
462
|
-
$schema: this.$schema,
|
|
463
|
-
name: this.name,
|
|
464
|
-
version: this.version,
|
|
465
|
-
options: this.options,
|
|
466
|
-
applications
|
|
467
|
-
};
|
|
663
|
+
return this.serialized.config;
|
|
468
664
|
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
version: this.version,
|
|
479
|
-
applications,
|
|
480
|
-
options: this.options,
|
|
481
|
-
$schema: this.$schema
|
|
482
|
-
},
|
|
483
|
-
overrides: (_a = this.overrides) == null ? void 0 : _a.serialize()
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
write(_) {
|
|
487
|
-
throw new MicrofrontendError(
|
|
488
|
-
`Writing to file to disk requires using an instance of "MicrofrontendConfig".`,
|
|
489
|
-
{ type: "config", subtype: "unsupported_operation" }
|
|
665
|
+
toClientConfig() {
|
|
666
|
+
const applications = Object.fromEntries(
|
|
667
|
+
Object.entries(this.childApplications).map(([name, application]) => [
|
|
668
|
+
name,
|
|
669
|
+
{
|
|
670
|
+
default: false,
|
|
671
|
+
routing: application.routing
|
|
672
|
+
}
|
|
673
|
+
])
|
|
490
674
|
);
|
|
675
|
+
if (this.defaultApplication) {
|
|
676
|
+
applications[this.defaultApplication.name] = {
|
|
677
|
+
default: true
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
return new MicrofrontendConfigClient({
|
|
681
|
+
applications
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
serialize() {
|
|
685
|
+
return this.serialized;
|
|
491
686
|
}
|
|
492
687
|
};
|
|
493
688
|
|
|
494
|
-
// src/config/
|
|
495
|
-
|
|
689
|
+
// src/config/microfrontends-config/isomorphic/child.ts
|
|
690
|
+
var MicrofrontendChildConfig = class extends MicrofrontendConfigIsomorphic {
|
|
691
|
+
constructor({
|
|
692
|
+
config,
|
|
693
|
+
overrides,
|
|
694
|
+
meta
|
|
695
|
+
}) {
|
|
696
|
+
super({ config, overrides, meta });
|
|
697
|
+
this.isMainConfig = false;
|
|
698
|
+
this.partOf = config.partOf;
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// src/config/microfrontends-config/isomorphic/main.ts
|
|
703
|
+
var MicrofrontendMainConfig = class extends MicrofrontendConfigIsomorphic {
|
|
704
|
+
constructor({
|
|
705
|
+
config,
|
|
706
|
+
overrides,
|
|
707
|
+
meta
|
|
708
|
+
}) {
|
|
709
|
+
var _a, _b, _c;
|
|
710
|
+
super({ config, overrides, meta });
|
|
711
|
+
this.isMainConfig = true;
|
|
712
|
+
const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
|
|
713
|
+
let defaultApplication;
|
|
714
|
+
for (const [appId, appConfig] of Object.entries(config.applications)) {
|
|
715
|
+
const appOverrides = !disableOverrides ? (_c = this.overrides) == null ? void 0 : _c.applications[appId] : void 0;
|
|
716
|
+
if (isDefaultApp(appConfig)) {
|
|
717
|
+
defaultApplication = new DefaultApplication(appId, {
|
|
718
|
+
app: appConfig,
|
|
719
|
+
overrides: appOverrides
|
|
720
|
+
});
|
|
721
|
+
} else {
|
|
722
|
+
this.childApplications[appId] = new ChildApplication(appId, {
|
|
723
|
+
app: appConfig,
|
|
724
|
+
overrides: appOverrides
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
if (!defaultApplication) {
|
|
729
|
+
throw new MicrofrontendError(
|
|
730
|
+
`Could not find default application in microfrontends configuration`,
|
|
731
|
+
{
|
|
732
|
+
type: "application",
|
|
733
|
+
subtype: "not_found"
|
|
734
|
+
}
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
this.defaultApplication = defaultApplication;
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
// src/config/microfrontends/isomorphic/index.ts
|
|
742
|
+
var Microfrontends = class {
|
|
743
|
+
constructor({
|
|
744
|
+
config,
|
|
745
|
+
overrides,
|
|
746
|
+
meta
|
|
747
|
+
}) {
|
|
748
|
+
if (isMainConfig(config)) {
|
|
749
|
+
this.config = new MicrofrontendMainConfig({ config, overrides, meta });
|
|
750
|
+
} else {
|
|
751
|
+
this.config = new MicrofrontendChildConfig({ config, overrides, meta });
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
isChildConfig() {
|
|
755
|
+
return this.config instanceof MicrofrontendChildConfig;
|
|
756
|
+
}
|
|
757
|
+
static fromEnv({
|
|
758
|
+
cookies,
|
|
759
|
+
meta
|
|
760
|
+
}) {
|
|
761
|
+
const config = MicrofrontendConfigIsomorphic.fromEnv({
|
|
762
|
+
cookies,
|
|
763
|
+
meta
|
|
764
|
+
});
|
|
765
|
+
return new Microfrontends(config.serialize());
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
// src/config/microfrontends/utils/find-repository-root.ts
|
|
770
|
+
import fs from "node:fs";
|
|
771
|
+
import path from "node:path";
|
|
772
|
+
var GIT_DIRECTORY = ".git";
|
|
773
|
+
function findRepositoryRoot(startDir) {
|
|
774
|
+
let currentDir = startDir || process.cwd();
|
|
775
|
+
while (currentDir !== path.parse(currentDir).root) {
|
|
776
|
+
const gitPath = path.join(currentDir, GIT_DIRECTORY);
|
|
777
|
+
if (fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory()) {
|
|
778
|
+
return currentDir;
|
|
779
|
+
}
|
|
780
|
+
currentDir = path.dirname(currentDir);
|
|
781
|
+
}
|
|
782
|
+
throw new Error(
|
|
783
|
+
"Repository root not found. Specify the root of the repository with the `repository.root` option."
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
// src/config/microfrontends/utils/find-package-path.ts
|
|
788
|
+
import { dirname } from "node:path";
|
|
789
|
+
import { readFileSync } from "node:fs";
|
|
790
|
+
import fg from "fast-glob";
|
|
791
|
+
var configCache = {};
|
|
792
|
+
function findPackagePathWithGlob({
|
|
793
|
+
repositoryRoot,
|
|
794
|
+
name
|
|
795
|
+
}) {
|
|
796
|
+
try {
|
|
797
|
+
const packageJsonPaths = fg.globSync("**/package.json", {
|
|
798
|
+
cwd: repositoryRoot,
|
|
799
|
+
absolute: true,
|
|
800
|
+
onlyFiles: true,
|
|
801
|
+
followSymbolicLinks: false,
|
|
802
|
+
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
803
|
+
});
|
|
804
|
+
const matchingPaths = [];
|
|
805
|
+
for (const packageJsonPath2 of packageJsonPaths) {
|
|
806
|
+
const packageJsonContent = readFileSync(packageJsonPath2, "utf-8");
|
|
807
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
808
|
+
if (packageJson.name === name) {
|
|
809
|
+
matchingPaths.push(packageJsonPath2);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
if (matchingPaths.length > 1) {
|
|
813
|
+
throw new Error(
|
|
814
|
+
`Found multiple packages with the name "${name}" in the repository: ${matchingPaths.join(", ")}`
|
|
815
|
+
);
|
|
816
|
+
}
|
|
817
|
+
if (matchingPaths.length === 0) {
|
|
818
|
+
throw new Error(
|
|
819
|
+
`Could not find package with the name "${name}" in the repository`
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
const [packageJsonPath] = matchingPaths;
|
|
823
|
+
return dirname(packageJsonPath);
|
|
824
|
+
} catch (error) {
|
|
825
|
+
return null;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
function findPackagePath(opts) {
|
|
829
|
+
const cacheKey = `${opts.repositoryRoot}-${opts.name}`;
|
|
830
|
+
if (configCache[cacheKey]) {
|
|
831
|
+
return configCache[cacheKey];
|
|
832
|
+
}
|
|
833
|
+
const result = findPackagePathWithGlob(opts);
|
|
834
|
+
if (!result) {
|
|
835
|
+
throw new Error(
|
|
836
|
+
`Could not find package with the name "${opts.name}" in the repository`
|
|
837
|
+
);
|
|
838
|
+
}
|
|
839
|
+
configCache[cacheKey] = result;
|
|
840
|
+
return result;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// src/config/microfrontends/utils/find-default-package.ts
|
|
844
|
+
import { dirname as dirname2 } from "node:path";
|
|
845
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
846
|
+
import { parse as parse2 } from "jsonc-parser";
|
|
847
|
+
import fg2 from "fast-glob";
|
|
496
848
|
|
|
497
849
|
// src/config/constants.ts
|
|
498
|
-
var
|
|
499
|
-
|
|
850
|
+
var CONFIGURATION_FILENAMES = [
|
|
851
|
+
"microfrontends.jsonc",
|
|
852
|
+
"microfrontends.json"
|
|
853
|
+
];
|
|
854
|
+
|
|
855
|
+
// src/config/microfrontends/utils/find-default-package.ts
|
|
856
|
+
var configCache2 = {};
|
|
857
|
+
function findDefaultMicrofrontendsPackages({
|
|
858
|
+
repositoryRoot,
|
|
859
|
+
applicationName
|
|
860
|
+
}) {
|
|
861
|
+
try {
|
|
862
|
+
const microfrontendsJsonPaths = fg2.globSync(
|
|
863
|
+
`**/{${CONFIGURATION_FILENAMES.join(",")}}`,
|
|
864
|
+
{
|
|
865
|
+
cwd: repositoryRoot,
|
|
866
|
+
absolute: true,
|
|
867
|
+
onlyFiles: true,
|
|
868
|
+
followSymbolicLinks: false,
|
|
869
|
+
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
870
|
+
}
|
|
871
|
+
);
|
|
872
|
+
const matchingPaths = [];
|
|
873
|
+
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
874
|
+
const microfrontendsJsonContent = readFileSync2(
|
|
875
|
+
microfrontendsJsonPath,
|
|
876
|
+
"utf-8"
|
|
877
|
+
);
|
|
878
|
+
const microfrontendsJson = parse2(microfrontendsJsonContent);
|
|
879
|
+
if (isMainConfig(microfrontendsJson) && microfrontendsJson.applications[applicationName]) {
|
|
880
|
+
matchingPaths.push(microfrontendsJsonPath);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
if (matchingPaths.length > 1) {
|
|
884
|
+
throw new Error(
|
|
885
|
+
`Found multiple default applications referencing "${applicationName}" in the repository, this is not yet supported.
|
|
886
|
+
${matchingPaths.join("\n \u2022 ")}`
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
if (matchingPaths.length === 0) {
|
|
890
|
+
throw new Error(
|
|
891
|
+
`Could not find default application with "applications.${applicationName}"`
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
const [packageJsonPath] = matchingPaths;
|
|
895
|
+
return dirname2(packageJsonPath);
|
|
896
|
+
} catch (error) {
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
function findDefaultMicrofrontendsPackage(opts) {
|
|
901
|
+
const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;
|
|
902
|
+
if (configCache2[cacheKey]) {
|
|
903
|
+
return configCache2[cacheKey];
|
|
904
|
+
}
|
|
905
|
+
const result = findDefaultMicrofrontendsPackages(opts);
|
|
906
|
+
if (!result) {
|
|
907
|
+
throw new Error(
|
|
908
|
+
`Error trying to resolve the main microfrontends configuration`
|
|
909
|
+
);
|
|
910
|
+
}
|
|
911
|
+
configCache2[cacheKey] = result;
|
|
912
|
+
return result;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// src/config/microfrontends/utils/is-monorepo.ts
|
|
916
|
+
import fs2 from "node:fs";
|
|
917
|
+
import path2 from "node:path";
|
|
918
|
+
function isMonorepo({
|
|
919
|
+
repositoryRoot
|
|
920
|
+
}) {
|
|
921
|
+
try {
|
|
922
|
+
if (fs2.existsSync(path2.join(repositoryRoot, "pnpm-workspace.yaml"))) {
|
|
923
|
+
return true;
|
|
924
|
+
}
|
|
925
|
+
if (fs2.existsSync(path2.join(repositoryRoot, "vlt-workspaces.json"))) {
|
|
926
|
+
return true;
|
|
927
|
+
}
|
|
928
|
+
const packageJsonPath = path2.join(repositoryRoot, "package.json");
|
|
929
|
+
if (!fs2.existsSync(packageJsonPath)) {
|
|
930
|
+
return false;
|
|
931
|
+
}
|
|
932
|
+
const packageJson = JSON.parse(
|
|
933
|
+
fs2.readFileSync(packageJsonPath, "utf-8")
|
|
934
|
+
);
|
|
935
|
+
return packageJson.workspaces !== void 0;
|
|
936
|
+
} catch (error) {
|
|
937
|
+
console.error("Error determining if repository is a monorepo", error);
|
|
938
|
+
return false;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// src/config/microfrontends/utils/find-package-root.ts
|
|
943
|
+
import fs3 from "node:fs";
|
|
944
|
+
import path3 from "node:path";
|
|
945
|
+
var PACKAGE_JSON = "package.json";
|
|
946
|
+
function findPackageRoot(startDir) {
|
|
947
|
+
let currentDir = startDir || process.cwd();
|
|
948
|
+
while (currentDir !== path3.parse(currentDir).root) {
|
|
949
|
+
const pkgJsonPath = path3.join(currentDir, PACKAGE_JSON);
|
|
950
|
+
if (fs3.existsSync(pkgJsonPath)) {
|
|
951
|
+
return currentDir;
|
|
952
|
+
}
|
|
953
|
+
currentDir = path3.dirname(currentDir);
|
|
954
|
+
}
|
|
955
|
+
throw new Error(
|
|
956
|
+
"Package root not found. Specify the root of the package with the `package.root` option."
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// src/config/microfrontends/utils/find-config.ts
|
|
961
|
+
import fs4 from "node:fs";
|
|
962
|
+
import { join } from "node:path";
|
|
963
|
+
function findConfig({ dir }) {
|
|
964
|
+
for (const filename of CONFIGURATION_FILENAMES) {
|
|
965
|
+
const maybeConfig = join(dir, filename);
|
|
966
|
+
if (fs4.existsSync(maybeConfig)) {
|
|
967
|
+
return maybeConfig;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
return null;
|
|
971
|
+
}
|
|
500
972
|
|
|
501
|
-
// src/config/utils/get-output-file-path.ts
|
|
502
|
-
|
|
973
|
+
// src/config/microfrontends/server/utils/get-output-file-path.ts
|
|
974
|
+
import path4 from "node:path";
|
|
975
|
+
|
|
976
|
+
// src/config/microfrontends/server/constants.ts
|
|
977
|
+
var MFE_CONFIG_DEFAULT_FILE_PATH = "microfrontends";
|
|
978
|
+
var MFE_CONFIG_DEFAULT_FILE_NAME = "microfrontends.json";
|
|
979
|
+
|
|
980
|
+
// src/utils/is-vercel.ts
|
|
981
|
+
function isVercel() {
|
|
982
|
+
return process.env.VERCEL === "1";
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
// src/config/microfrontends/server/utils/get-output-file-path.ts
|
|
986
|
+
function getOutputFilePath() {
|
|
503
987
|
if (isVercel()) {
|
|
504
|
-
return
|
|
988
|
+
return path4.join(
|
|
505
989
|
".vercel",
|
|
506
|
-
|
|
507
|
-
|
|
990
|
+
MFE_CONFIG_DEFAULT_FILE_PATH,
|
|
991
|
+
MFE_CONFIG_DEFAULT_FILE_NAME
|
|
508
992
|
);
|
|
509
993
|
}
|
|
510
|
-
return
|
|
994
|
+
return path4.join(MFE_CONFIG_DEFAULT_FILE_PATH, MFE_CONFIG_DEFAULT_FILE_NAME);
|
|
511
995
|
}
|
|
512
996
|
|
|
513
|
-
// src/config/validation.ts
|
|
514
|
-
import { parse } from "jsonc-parser";
|
|
515
|
-
import { pathToRegexp, parse as parsePathRegexp } from "path-to-regexp";
|
|
997
|
+
// src/config/microfrontends/server/validation.ts
|
|
998
|
+
import { parse as parse3 } from "jsonc-parser";
|
|
516
999
|
import { Ajv } from "ajv";
|
|
517
1000
|
|
|
518
|
-
// src/config/types.ts
|
|
519
|
-
var isDefaultApplicationConfig = (app) => app.default && typeof app.routing === "undefined";
|
|
520
|
-
|
|
521
1001
|
// schema/schema.json
|
|
522
1002
|
var schema_default = {
|
|
523
1003
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
524
1004
|
$ref: "#/definitions/Config",
|
|
525
1005
|
definitions: {
|
|
526
1006
|
Config: {
|
|
1007
|
+
anyOf: [
|
|
1008
|
+
{
|
|
1009
|
+
$ref: "#/definitions/MainConfig"
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
$ref: "#/definitions/ChildConfig"
|
|
1013
|
+
}
|
|
1014
|
+
]
|
|
1015
|
+
},
|
|
1016
|
+
MainConfig: {
|
|
527
1017
|
type: "object",
|
|
528
1018
|
properties: {
|
|
529
|
-
version: {
|
|
530
|
-
type: "string"
|
|
531
|
-
},
|
|
532
1019
|
$schema: {
|
|
533
1020
|
type: "string"
|
|
534
1021
|
},
|
|
535
|
-
|
|
1022
|
+
version: {
|
|
536
1023
|
type: "string",
|
|
537
|
-
|
|
1024
|
+
const: "2"
|
|
1025
|
+
},
|
|
1026
|
+
options: {
|
|
1027
|
+
$ref: "#/definitions/Options"
|
|
1028
|
+
},
|
|
1029
|
+
remotes: {
|
|
1030
|
+
type: "object",
|
|
1031
|
+
additionalProperties: {
|
|
1032
|
+
$ref: "#/definitions/Application"
|
|
1033
|
+
},
|
|
1034
|
+
description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
|
|
538
1035
|
},
|
|
539
1036
|
applications: {
|
|
540
|
-
$ref: "#/definitions/
|
|
1037
|
+
$ref: "#/definitions/ApplicationRouting",
|
|
1038
|
+
description: "Mapping of application names to the routes that they host. Only needs to be defined in the application that owns the primary microfrontend domain"
|
|
1039
|
+
}
|
|
1040
|
+
},
|
|
1041
|
+
required: ["applications", "version"],
|
|
1042
|
+
additionalProperties: false
|
|
1043
|
+
},
|
|
1044
|
+
Options: {
|
|
1045
|
+
type: "object",
|
|
1046
|
+
properties: {
|
|
1047
|
+
vercel: {
|
|
1048
|
+
$ref: "#/definitions/VercelOptions",
|
|
1049
|
+
description: "Micro-Frontends wide options for Vercel."
|
|
541
1050
|
},
|
|
542
|
-
|
|
543
|
-
$ref: "#/definitions/
|
|
544
|
-
description: "
|
|
1051
|
+
localProxy: {
|
|
1052
|
+
$ref: "#/definitions/LocalProxyOptions",
|
|
1053
|
+
description: "Options for local proxy."
|
|
545
1054
|
}
|
|
546
1055
|
},
|
|
547
|
-
|
|
548
|
-
description: "Configuration for micro-frontend applications\n\nTODO: Add proxy configuration"
|
|
1056
|
+
additionalProperties: false
|
|
549
1057
|
},
|
|
550
|
-
|
|
1058
|
+
VercelOptions: {
|
|
551
1059
|
type: "object",
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
1060
|
+
properties: {
|
|
1061
|
+
teamSlug: {
|
|
1062
|
+
type: "string",
|
|
1063
|
+
description: "Team slug for the Vercel team"
|
|
1064
|
+
},
|
|
1065
|
+
disableOverrides: {
|
|
1066
|
+
type: "boolean",
|
|
1067
|
+
description: "If you want to disable the overrides for the site. For example, if you are managing rewrites between applications externally, you may wish to disable the overrides on the toolbar as they will have no effect."
|
|
1068
|
+
}
|
|
1069
|
+
},
|
|
1070
|
+
additionalProperties: false
|
|
555
1071
|
},
|
|
556
|
-
|
|
1072
|
+
LocalProxyOptions: {
|
|
1073
|
+
type: "object",
|
|
1074
|
+
properties: {
|
|
1075
|
+
port: {
|
|
1076
|
+
type: "number",
|
|
1077
|
+
description: "The port number used by the local proxy server.\n\nThe default is `3024`."
|
|
1078
|
+
}
|
|
1079
|
+
},
|
|
1080
|
+
additionalProperties: false
|
|
1081
|
+
},
|
|
1082
|
+
Application: {
|
|
557
1083
|
anyOf: [
|
|
558
1084
|
{
|
|
559
|
-
$ref: "#/definitions/
|
|
1085
|
+
$ref: "#/definitions/DefaultApplication"
|
|
560
1086
|
},
|
|
561
1087
|
{
|
|
562
|
-
$ref: "#/definitions/
|
|
1088
|
+
$ref: "#/definitions/ChildApplication"
|
|
563
1089
|
}
|
|
564
|
-
]
|
|
565
|
-
description: "A Micro-Frontend Deployment Target"
|
|
1090
|
+
]
|
|
566
1091
|
},
|
|
567
|
-
|
|
1092
|
+
DefaultApplication: {
|
|
568
1093
|
type: "object",
|
|
569
1094
|
properties: {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
const: true,
|
|
573
|
-
description: "The default application is used no other application is matched via the routing config"
|
|
574
|
-
},
|
|
575
|
-
routing: {
|
|
576
|
-
$ref: "#/definitions/Routing"
|
|
1095
|
+
vercel: {
|
|
1096
|
+
$ref: "#/definitions/Vercel"
|
|
577
1097
|
},
|
|
578
1098
|
development: {
|
|
579
|
-
|
|
580
|
-
properties: {
|
|
581
|
-
local: {
|
|
582
|
-
$ref: "#/definitions/HostConfig"
|
|
583
|
-
},
|
|
584
|
-
fallback: {
|
|
585
|
-
$ref: "#/definitions/HostConfig",
|
|
586
|
-
description: "Fallback for local development, could be a host config that points to any environment. If this is not provided, or the application is not running - requests to the application in local development will error."
|
|
587
|
-
},
|
|
588
|
-
task: {
|
|
589
|
-
type: "string",
|
|
590
|
-
description: "Optional task to run when starting the development server. Should reference a script in the package.json of the application."
|
|
591
|
-
}
|
|
592
|
-
},
|
|
593
|
-
required: ["local"]
|
|
1099
|
+
$ref: "#/definitions/Development"
|
|
594
1100
|
},
|
|
595
1101
|
production: {
|
|
596
1102
|
$ref: "#/definitions/HostConfig"
|
|
597
|
-
},
|
|
598
|
-
metadata: {
|
|
599
|
-
type: "object",
|
|
600
|
-
additionalProperties: {
|
|
601
|
-
type: "string"
|
|
602
|
-
}
|
|
603
|
-
},
|
|
604
|
-
federation: {
|
|
605
|
-
type: "object",
|
|
606
|
-
properties: {
|
|
607
|
-
exposes: {
|
|
608
|
-
type: "array",
|
|
609
|
-
items: {
|
|
610
|
-
type: "object",
|
|
611
|
-
properties: {
|
|
612
|
-
name: {
|
|
613
|
-
type: "string",
|
|
614
|
-
description: "The name of the module - should be used when importing the module from another application"
|
|
615
|
-
},
|
|
616
|
-
path: {
|
|
617
|
-
type: "string",
|
|
618
|
-
description: "Relative path to the module within its `application`"
|
|
619
|
-
}
|
|
620
|
-
},
|
|
621
|
-
required: ["name", "path"]
|
|
622
|
-
},
|
|
623
|
-
description: "Modules that are exposed by this application"
|
|
624
|
-
},
|
|
625
|
-
uses: {
|
|
626
|
-
type: "array",
|
|
627
|
-
items: {
|
|
628
|
-
type: "string"
|
|
629
|
-
},
|
|
630
|
-
description: "Modules that are used by this application. Only the name of the module is required."
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
},
|
|
634
|
-
vercel: {
|
|
635
|
-
$ref: "#/definitions/Vercel"
|
|
636
1103
|
}
|
|
637
1104
|
},
|
|
638
|
-
required: ["
|
|
1105
|
+
required: ["production"],
|
|
1106
|
+
additionalProperties: false
|
|
639
1107
|
},
|
|
640
|
-
|
|
1108
|
+
Vercel: {
|
|
641
1109
|
type: "object",
|
|
642
1110
|
properties: {
|
|
643
|
-
|
|
1111
|
+
projectId: {
|
|
644
1112
|
type: "string",
|
|
645
|
-
description: "
|
|
646
|
-
},
|
|
647
|
-
matches: {
|
|
648
|
-
type: "array",
|
|
649
|
-
items: {
|
|
650
|
-
$ref: "#/definitions/PathGroup"
|
|
651
|
-
},
|
|
652
|
-
description: "Path expressions that are routed to this application."
|
|
1113
|
+
description: "Vercel project ID"
|
|
653
1114
|
}
|
|
654
1115
|
},
|
|
655
|
-
required: ["
|
|
1116
|
+
required: ["projectId"],
|
|
1117
|
+
additionalProperties: false
|
|
656
1118
|
},
|
|
657
|
-
|
|
1119
|
+
Development: {
|
|
658
1120
|
type: "object",
|
|
659
1121
|
properties: {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
description: "Optional group name for the paths"
|
|
1122
|
+
local: {
|
|
1123
|
+
$ref: "#/definitions/LocalHostConfig"
|
|
663
1124
|
},
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
flag: {
|
|
668
|
-
type: "string",
|
|
669
|
-
description: "flag name that can be used to enable/disable all paths in the group"
|
|
670
|
-
}
|
|
671
|
-
}
|
|
1125
|
+
fallback: {
|
|
1126
|
+
$ref: "#/definitions/HostConfig",
|
|
1127
|
+
description: "Fallback for local development, could be a host config that points to any environment. If this is not provided, or the application is not running - requests to the application in local development will error."
|
|
672
1128
|
},
|
|
673
|
-
|
|
674
|
-
type: "
|
|
675
|
-
|
|
676
|
-
type: "string"
|
|
677
|
-
}
|
|
1129
|
+
task: {
|
|
1130
|
+
type: "string",
|
|
1131
|
+
description: "Optional task to run when starting the development server. Should reference a script in the package.json of the application."
|
|
678
1132
|
}
|
|
679
1133
|
},
|
|
680
|
-
|
|
1134
|
+
additionalProperties: false
|
|
681
1135
|
},
|
|
682
|
-
|
|
1136
|
+
LocalHostConfig: {
|
|
683
1137
|
type: "object",
|
|
1138
|
+
additionalProperties: false,
|
|
684
1139
|
properties: {
|
|
685
|
-
protocol: {
|
|
686
|
-
type: "string",
|
|
687
|
-
enum: ["http", "https"],
|
|
688
|
-
description: 'The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n* @defaultValue "https"'
|
|
689
|
-
},
|
|
690
1140
|
host: {
|
|
691
1141
|
type: "string",
|
|
692
1142
|
description: "The hostname or IP address of the server. This can be a domain name (e.g., `example.com`) or an IP address (e.g., `192.168.1.1`)."
|
|
693
1143
|
},
|
|
1144
|
+
protocol: {
|
|
1145
|
+
type: "string",
|
|
1146
|
+
enum: ["http", "https"],
|
|
1147
|
+
description: 'The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n* @defaultValue "http" for local development, "https" for otherwise'
|
|
1148
|
+
},
|
|
694
1149
|
port: {
|
|
695
1150
|
type: "number",
|
|
696
|
-
description: "The port number to be used for the connection. Common values include `80` for HTTP and `443` for HTTPS
|
|
1151
|
+
description: "The port number to be used for the connection. Common values include `80` for HTTP and `443` for HTTPS."
|
|
697
1152
|
}
|
|
698
|
-
}
|
|
699
|
-
required: ["host"]
|
|
1153
|
+
}
|
|
700
1154
|
},
|
|
701
|
-
|
|
1155
|
+
HostConfig: {
|
|
702
1156
|
type: "object",
|
|
703
1157
|
properties: {
|
|
704
|
-
|
|
705
|
-
type: "string",
|
|
706
|
-
description: "Vercel project ID"
|
|
707
|
-
},
|
|
708
|
-
projectName: {
|
|
1158
|
+
protocol: {
|
|
709
1159
|
type: "string",
|
|
710
|
-
|
|
1160
|
+
enum: ["http", "https"],
|
|
1161
|
+
description: 'The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n* @defaultValue "http" for local development, "https" for otherwise'
|
|
711
1162
|
},
|
|
712
|
-
|
|
1163
|
+
host: {
|
|
713
1164
|
type: "string",
|
|
714
|
-
description: "The
|
|
1165
|
+
description: "The hostname or IP address of the server. This can be a domain name (e.g., `example.com`) or an IP address (e.g., `192.168.1.1`)."
|
|
715
1166
|
},
|
|
716
|
-
|
|
717
|
-
type: "
|
|
718
|
-
description: "
|
|
1167
|
+
port: {
|
|
1168
|
+
type: "number",
|
|
1169
|
+
description: "The port number to be used for the connection. Common values include `80` for HTTP and `443` for HTTPS."
|
|
719
1170
|
}
|
|
720
1171
|
},
|
|
721
|
-
required: ["
|
|
1172
|
+
required: ["host"],
|
|
1173
|
+
additionalProperties: false
|
|
722
1174
|
},
|
|
723
|
-
|
|
1175
|
+
ChildApplication: {
|
|
724
1176
|
type: "object",
|
|
725
1177
|
properties: {
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
const: false,
|
|
729
|
-
description: "The default application is used no other application is matched via the routing config"
|
|
730
|
-
},
|
|
731
|
-
routing: {
|
|
732
|
-
$ref: "#/definitions/Routing"
|
|
1178
|
+
vercel: {
|
|
1179
|
+
$ref: "#/definitions/Vercel"
|
|
733
1180
|
},
|
|
734
1181
|
development: {
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
fallback: {
|
|
741
|
-
$ref: "#/definitions/HostConfig",
|
|
742
|
-
description: "Fallback for local development, could be a host config that points to any environment. If this is not provided, or the application is not running - requests to the application in local development will error."
|
|
743
|
-
},
|
|
744
|
-
task: {
|
|
745
|
-
type: "string",
|
|
746
|
-
description: "Optional task to run when starting the development server. Should reference a script in the package.json of the application."
|
|
747
|
-
}
|
|
748
|
-
},
|
|
749
|
-
required: ["local"]
|
|
1182
|
+
$ref: "#/definitions/Development"
|
|
1183
|
+
},
|
|
1184
|
+
routing: {
|
|
1185
|
+
$ref: "#/definitions/Routing",
|
|
1186
|
+
description: "Groups of path expressions that are routed to this application."
|
|
750
1187
|
},
|
|
751
1188
|
production: {
|
|
752
1189
|
$ref: "#/definitions/HostConfig"
|
|
753
|
-
},
|
|
754
|
-
metadata: {
|
|
755
|
-
type: "object",
|
|
756
|
-
additionalProperties: {
|
|
757
|
-
type: "string"
|
|
758
|
-
}
|
|
759
|
-
},
|
|
760
|
-
federation: {
|
|
761
|
-
type: "object",
|
|
762
|
-
properties: {
|
|
763
|
-
exposes: {
|
|
764
|
-
type: "array",
|
|
765
|
-
items: {
|
|
766
|
-
type: "object",
|
|
767
|
-
properties: {
|
|
768
|
-
name: {
|
|
769
|
-
type: "string",
|
|
770
|
-
description: "The name of the module - should be used when importing the module from another application"
|
|
771
|
-
},
|
|
772
|
-
path: {
|
|
773
|
-
type: "string",
|
|
774
|
-
description: "Relative path to the module within its `application`"
|
|
775
|
-
}
|
|
776
|
-
},
|
|
777
|
-
required: ["name", "path"]
|
|
778
|
-
},
|
|
779
|
-
description: "Modules that are exposed by this application"
|
|
780
|
-
},
|
|
781
|
-
uses: {
|
|
782
|
-
type: "array",
|
|
783
|
-
items: {
|
|
784
|
-
type: "string"
|
|
785
|
-
},
|
|
786
|
-
description: "Modules that are used by this application. Only the name of the module is required."
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
},
|
|
790
|
-
vercel: {
|
|
791
|
-
$ref: "#/definitions/Vercel"
|
|
792
1190
|
}
|
|
793
1191
|
},
|
|
794
|
-
required: ["
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
description: "Micro-Frontends wide options for Vercel."
|
|
802
|
-
},
|
|
803
|
-
localProxy: {
|
|
804
|
-
$ref: "#/definitions/LocalProxyOptions",
|
|
805
|
-
description: "Options for local proxy."
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
},
|
|
809
|
-
VercelOptions: {
|
|
810
|
-
type: "object",
|
|
811
|
-
properties: {
|
|
812
|
-
previewDeploymentSuffix: {
|
|
813
|
-
type: "string",
|
|
814
|
-
description: "If your team uses a custom Preview Deployment Suffix, please specify it here. See https://vercel.com/docs/deployments/preview-deployment-suffix. The default is `vercel.app`."
|
|
815
|
-
},
|
|
816
|
-
teamSlug: {
|
|
817
|
-
type: "string",
|
|
818
|
-
description: "Team slug for the Vercel team"
|
|
819
|
-
},
|
|
820
|
-
disableOverrides: {
|
|
821
|
-
type: "boolean",
|
|
822
|
-
description: "If you want to disable the overrides for the site. For example, if you are managing rewrites between applications externally, you may wish to disable the overrides on the toolbar as they will have no effect."
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
},
|
|
826
|
-
LocalProxyOptions: {
|
|
827
|
-
type: "object",
|
|
828
|
-
properties: {
|
|
829
|
-
port: {
|
|
830
|
-
type: "number",
|
|
831
|
-
description: "The port number used by the local proxy server.\n\nThe default is `3024`."
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
};
|
|
837
|
-
|
|
838
|
-
// src/config/utils/load-schema.ts
|
|
839
|
-
var SCHEMA = schema_default;
|
|
840
|
-
|
|
841
|
-
// src/config/validation.ts
|
|
842
|
-
var validateSchema = (configString) => {
|
|
843
|
-
const parsedConfig = parse(configString);
|
|
844
|
-
const ajv = new Ajv();
|
|
845
|
-
const validate = ajv.compile(SCHEMA);
|
|
846
|
-
const isValid = validate(parsedConfig);
|
|
847
|
-
if (!isValid) {
|
|
848
|
-
throw new MicrofrontendError(
|
|
849
|
-
`Invalid config: ${ajv.errorsText(validate.errors)}`,
|
|
850
|
-
{ type: "config", subtype: "does_not_match_schema" }
|
|
851
|
-
);
|
|
852
|
-
}
|
|
853
|
-
return parsedConfig;
|
|
854
|
-
};
|
|
855
|
-
var SUPPORTED_VERSIONS2 = ["1"];
|
|
856
|
-
var validateVersion = (version) => {
|
|
857
|
-
if (!SUPPORTED_VERSIONS2.includes(version)) {
|
|
858
|
-
throw new MicrofrontendError(
|
|
859
|
-
`Unsupported version: ${version}. Supported versions are: ${SUPPORTED_VERSIONS2.join(
|
|
860
|
-
", "
|
|
861
|
-
)}`,
|
|
862
|
-
{ type: "config", subtype: "unsupported_version" }
|
|
863
|
-
);
|
|
864
|
-
}
|
|
865
|
-
};
|
|
866
|
-
function validateMainPath(applicationConfigsById) {
|
|
867
|
-
for (const [id, app] of Object.entries(applicationConfigsById)) {
|
|
868
|
-
const { defaultRoute } = app.vercel ?? {};
|
|
869
|
-
if (!defaultRoute) {
|
|
870
|
-
continue;
|
|
871
|
-
}
|
|
872
|
-
if (isDefaultApplicationConfig(app)) {
|
|
873
|
-
const pathsWithApp = [];
|
|
874
|
-
for (const [otherId, otherApp] of Object.entries(
|
|
875
|
-
applicationConfigsById
|
|
876
|
-
)) {
|
|
877
|
-
if (isDefaultApplicationConfig(otherApp)) {
|
|
878
|
-
continue;
|
|
879
|
-
}
|
|
880
|
-
pathsWithApp.push({
|
|
881
|
-
id: otherId,
|
|
882
|
-
paths: otherApp.routing.matches.flatMap((match) => match.paths)
|
|
883
|
-
});
|
|
884
|
-
}
|
|
885
|
-
for (const { id: otherId, paths } of pathsWithApp) {
|
|
886
|
-
const isValid = paths.every((path3) => {
|
|
887
|
-
const matcher = pathToRegexp(path3);
|
|
888
|
-
return !matcher.test(defaultRoute);
|
|
889
|
-
});
|
|
890
|
-
if (!isValid) {
|
|
891
|
-
throw new MicrofrontendError(
|
|
892
|
-
`default route "${defaultRoute}" cannot be used for "${id}" because it is matched by "${otherId}"`,
|
|
893
|
-
{ type: "config", subtype: "invalid_main_path" }
|
|
894
|
-
);
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
} else {
|
|
898
|
-
const allPaths = app.routing.matches.flatMap((match) => match.paths);
|
|
899
|
-
const isValid = allPaths.some((path3) => {
|
|
900
|
-
const matcher = pathToRegexp(path3);
|
|
901
|
-
return matcher.test(defaultRoute);
|
|
902
|
-
});
|
|
903
|
-
if (!isValid) {
|
|
904
|
-
throw new MicrofrontendError(
|
|
905
|
-
`default route "${defaultRoute}" is not included by the routing config for application "${id}"`,
|
|
906
|
-
{ type: "config", subtype: "invalid_main_path" }
|
|
907
|
-
);
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
var validatePaths = (applicationConfigsById) => {
|
|
913
|
-
const pathsByApplicationId = /* @__PURE__ */ new Map();
|
|
914
|
-
const errors = [];
|
|
915
|
-
for (const [id, app] of Object.entries(applicationConfigsById)) {
|
|
916
|
-
if (isDefaultApplicationConfig(app)) {
|
|
917
|
-
continue;
|
|
918
|
-
}
|
|
919
|
-
for (const pathMatch of app.routing.matches) {
|
|
920
|
-
for (const path3 of pathMatch.paths) {
|
|
921
|
-
const maybeError = validatePathExpression(path3);
|
|
922
|
-
if (maybeError) {
|
|
923
|
-
errors.push(maybeError);
|
|
924
|
-
}
|
|
925
|
-
const existing = pathsByApplicationId.get(path3);
|
|
926
|
-
if (existing) {
|
|
927
|
-
existing.applications.push(id);
|
|
928
|
-
} else {
|
|
929
|
-
pathsByApplicationId.set(path3, {
|
|
930
|
-
applications: [id],
|
|
931
|
-
matcher: pathToRegexp(path3),
|
|
932
|
-
applicationId: id
|
|
933
|
-
});
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
const entries = Array.from(pathsByApplicationId.entries());
|
|
939
|
-
entries.forEach(([path3, { applications: ids, matcher, applicationId }]) => {
|
|
940
|
-
if (ids.length > 1) {
|
|
941
|
-
errors.push(
|
|
942
|
-
`Duplicate path "${path3}" for applications "${ids.join(", ")}"`
|
|
943
|
-
);
|
|
944
|
-
}
|
|
945
|
-
entries.forEach(
|
|
946
|
-
([
|
|
947
|
-
matchPath,
|
|
948
|
-
{ applications: matchIds, applicationId: matchApplicationId }
|
|
949
|
-
]) => {
|
|
950
|
-
if (path3 === matchPath) {
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
|
-
if (applicationId === matchApplicationId) {
|
|
954
|
-
return;
|
|
955
|
-
}
|
|
956
|
-
if (matcher.test(matchPath)) {
|
|
957
|
-
const source = `"${path3}" of application${ids.length > 0 ? "s" : ""} ${ids.join(", ")}`;
|
|
958
|
-
const destination = `"${matchPath}" of application${matchIds.length > 0 ? "s" : ""} ${matchIds.join(", ")}`;
|
|
959
|
-
errors.push(
|
|
960
|
-
`Overlapping path detected between ${source} and ${destination}`
|
|
961
|
-
);
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
);
|
|
965
|
-
});
|
|
966
|
-
if (errors.length) {
|
|
967
|
-
throw new MicrofrontendError(`Invalid paths: ${errors.join(", ")}`, {
|
|
968
|
-
type: "config",
|
|
969
|
-
subtype: "conflicting_paths"
|
|
970
|
-
});
|
|
971
|
-
}
|
|
972
|
-
};
|
|
973
|
-
var PATH_DEFAULT_PATTERN = "[^\\/#\\?]+?";
|
|
974
|
-
function validatePathExpression(path3) {
|
|
975
|
-
const tokens = parsePathRegexp(path3);
|
|
976
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
977
|
-
const token = tokens[i];
|
|
978
|
-
if (token === void 0) {
|
|
979
|
-
return `token ${i} in ${path3} is undefined, this shouldn't happen`;
|
|
980
|
-
}
|
|
981
|
-
if (typeof token !== "string") {
|
|
982
|
-
if (token.pattern !== PATH_DEFAULT_PATTERN) {
|
|
983
|
-
return `Path ${path3} cannot use a regular expression wildcard`;
|
|
984
|
-
}
|
|
985
|
-
if (token.prefix !== "/") {
|
|
986
|
-
return `Wildcard :${token.name} must be immediately after a / in ${path3}`;
|
|
987
|
-
}
|
|
988
|
-
if (token.suffix) {
|
|
989
|
-
return `Wildcard suffix on :${token.name} is not allowed. Suffixes are not supported`;
|
|
1192
|
+
required: ["routing"],
|
|
1193
|
+
additionalProperties: false
|
|
1194
|
+
},
|
|
1195
|
+
Routing: {
|
|
1196
|
+
type: "array",
|
|
1197
|
+
items: {
|
|
1198
|
+
$ref: "#/definitions/PathGroup"
|
|
990
1199
|
}
|
|
991
|
-
|
|
992
|
-
|
|
1200
|
+
},
|
|
1201
|
+
PathGroup: {
|
|
1202
|
+
type: "object",
|
|
1203
|
+
properties: {
|
|
1204
|
+
group: {
|
|
1205
|
+
type: "string",
|
|
1206
|
+
description: "Optional group name for the paths"
|
|
1207
|
+
},
|
|
1208
|
+
flag: {
|
|
1209
|
+
type: "string",
|
|
1210
|
+
description: "flag name that can be used to enable/disable all paths in the group"
|
|
1211
|
+
},
|
|
1212
|
+
paths: {
|
|
1213
|
+
type: "array",
|
|
1214
|
+
items: {
|
|
1215
|
+
type: "string"
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
},
|
|
1219
|
+
required: ["paths"],
|
|
1220
|
+
additionalProperties: false
|
|
1221
|
+
},
|
|
1222
|
+
ApplicationRouting: {
|
|
1223
|
+
type: "object",
|
|
1224
|
+
additionalProperties: {
|
|
1225
|
+
$ref: "#/definitions/Application"
|
|
993
1226
|
}
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
);
|
|
1227
|
+
},
|
|
1228
|
+
ChildConfig: {
|
|
1229
|
+
type: "object",
|
|
1230
|
+
properties: {
|
|
1231
|
+
$schema: {
|
|
1232
|
+
type: "string"
|
|
1233
|
+
},
|
|
1234
|
+
version: {
|
|
1235
|
+
type: "string",
|
|
1236
|
+
const: "2"
|
|
1237
|
+
},
|
|
1238
|
+
options: {
|
|
1239
|
+
$ref: "#/definitions/Options"
|
|
1240
|
+
},
|
|
1241
|
+
remotes: {
|
|
1242
|
+
type: "object",
|
|
1243
|
+
additionalProperties: {
|
|
1244
|
+
$ref: "#/definitions/Application"
|
|
1245
|
+
},
|
|
1246
|
+
description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
|
|
1247
|
+
},
|
|
1248
|
+
partOf: {
|
|
1249
|
+
type: "string",
|
|
1250
|
+
description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
|
|
1251
|
+
}
|
|
1252
|
+
},
|
|
1253
|
+
required: ["partOf", "version"],
|
|
1254
|
+
additionalProperties: false
|
|
1023
1255
|
}
|
|
1024
1256
|
}
|
|
1025
1257
|
};
|
|
1026
1258
|
|
|
1027
|
-
// src/config/utils/
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
development: application.development,
|
|
1042
|
-
vercel: application.vercel
|
|
1043
|
-
};
|
|
1044
|
-
if (application.default) {
|
|
1045
|
-
return common;
|
|
1259
|
+
// src/config/schema/utils/load.ts
|
|
1260
|
+
var SCHEMA = schema_default;
|
|
1261
|
+
|
|
1262
|
+
// src/config/microfrontends/server/validation.ts
|
|
1263
|
+
function validateSchema(configString) {
|
|
1264
|
+
const parsedConfig = parse3(configString);
|
|
1265
|
+
const ajv = new Ajv();
|
|
1266
|
+
const validate = ajv.compile(SCHEMA);
|
|
1267
|
+
const isValid = validate(parsedConfig);
|
|
1268
|
+
if (!isValid) {
|
|
1269
|
+
throw new MicrofrontendError(
|
|
1270
|
+
`Invalid config: ${ajv.errorsText(validate.errors)}`,
|
|
1271
|
+
{ type: "config", subtype: "does_not_match_schema" }
|
|
1272
|
+
);
|
|
1046
1273
|
}
|
|
1047
|
-
return
|
|
1048
|
-
...common,
|
|
1049
|
-
routing: convertV1RoutingToV2Routing(application.routing)
|
|
1050
|
-
};
|
|
1274
|
+
return parsedConfig;
|
|
1051
1275
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1276
|
+
|
|
1277
|
+
// src/config/microfrontends/server/index.ts
|
|
1278
|
+
var MicrofrontendsServer = class extends Microfrontends {
|
|
1279
|
+
/**
|
|
1280
|
+
* Writes the configuration to a file.
|
|
1281
|
+
*/
|
|
1282
|
+
writeConfig(opts = {
|
|
1283
|
+
pretty: true
|
|
1284
|
+
}) {
|
|
1285
|
+
const outputPath = getOutputFilePath();
|
|
1286
|
+
fs5.mkdirSync(dirname3(outputPath), { recursive: true });
|
|
1287
|
+
fs5.writeFileSync(
|
|
1288
|
+
outputPath,
|
|
1289
|
+
JSON.stringify(
|
|
1290
|
+
this.config.toSchemaJson(),
|
|
1291
|
+
null,
|
|
1292
|
+
opts.pretty ?? true ? 2 : void 0
|
|
1068
1293
|
)
|
|
1069
|
-
|
|
1070
|
-
}
|
|
1071
|
-
const defaultApplication = Object.entries(config.applications).find(
|
|
1072
|
-
([, application]) => application.default
|
|
1073
|
-
);
|
|
1074
|
-
if (!defaultApplication) {
|
|
1075
|
-
throw new Error("No default application found in the config");
|
|
1294
|
+
);
|
|
1076
1295
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1296
|
+
// --------- Static Methods ---------
|
|
1297
|
+
/**
|
|
1298
|
+
* Generates a MicrofrontendsServer instance from an unknown object.
|
|
1299
|
+
*/
|
|
1300
|
+
static fromUnknown({
|
|
1301
|
+
config,
|
|
1302
|
+
cookies,
|
|
1303
|
+
meta
|
|
1304
|
+
}) {
|
|
1305
|
+
const overrides = cookies ? parseOverrides(cookies) : void 0;
|
|
1306
|
+
if (typeof config === "string") {
|
|
1307
|
+
return new MicrofrontendsServer({
|
|
1308
|
+
config: MicrofrontendsServer.validate(config),
|
|
1309
|
+
overrides,
|
|
1310
|
+
meta
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
if (typeof config === "object") {
|
|
1314
|
+
return new MicrofrontendsServer({
|
|
1315
|
+
config,
|
|
1316
|
+
overrides,
|
|
1317
|
+
meta
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
throw new MicrofrontendError(
|
|
1321
|
+
"Invalid config: must be a string or an object",
|
|
1322
|
+
{ type: "config", subtype: "does_not_match_schema" }
|
|
1323
|
+
);
|
|
1104
1324
|
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Generates a MicrofrontendsServer instance from the environment.
|
|
1327
|
+
* Uses additional validation that is only available when in a node runtime
|
|
1328
|
+
*/
|
|
1105
1329
|
static fromEnv({
|
|
1106
|
-
cookies
|
|
1330
|
+
cookies,
|
|
1331
|
+
meta
|
|
1107
1332
|
}) {
|
|
1108
|
-
return new
|
|
1109
|
-
config:
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
overrides: Overrides.parseOverrides(cookies)
|
|
1333
|
+
return new MicrofrontendsServer({
|
|
1334
|
+
config: MicrofrontendsServer.validate(getConfigStringFromEnv()),
|
|
1335
|
+
overrides: parseOverrides(cookies),
|
|
1336
|
+
meta
|
|
1113
1337
|
});
|
|
1114
1338
|
}
|
|
1339
|
+
/**
|
|
1340
|
+
* Validates the configuration against the JSON schema
|
|
1341
|
+
*/
|
|
1342
|
+
static validate(config) {
|
|
1343
|
+
if (typeof config === "string") {
|
|
1344
|
+
const c = validateSchema(config);
|
|
1345
|
+
return c;
|
|
1346
|
+
}
|
|
1347
|
+
return config;
|
|
1348
|
+
}
|
|
1349
|
+
/**
|
|
1350
|
+
* Looks up the configuration by inferring the package root and looking for a microfrontends config file. If a file is not found,
|
|
1351
|
+
* it will look for a package in the repository with a microfrontends file that contains the current application
|
|
1352
|
+
* and use that configuration.
|
|
1353
|
+
*
|
|
1354
|
+
* This can return either a Child or Main configuration.
|
|
1355
|
+
*/
|
|
1356
|
+
static infer({
|
|
1357
|
+
directory,
|
|
1358
|
+
filePath,
|
|
1359
|
+
meta,
|
|
1360
|
+
cookies,
|
|
1361
|
+
options
|
|
1362
|
+
} = {}) {
|
|
1363
|
+
if (filePath && meta) {
|
|
1364
|
+
return MicrofrontendsServer.fromFile({
|
|
1365
|
+
filePath,
|
|
1366
|
+
cookies,
|
|
1367
|
+
meta,
|
|
1368
|
+
options
|
|
1369
|
+
});
|
|
1370
|
+
}
|
|
1371
|
+
try {
|
|
1372
|
+
const packageRoot = findPackageRoot(directory);
|
|
1373
|
+
const packageJsonPath = join2(packageRoot, "package.json");
|
|
1374
|
+
const packageJson = JSON.parse(
|
|
1375
|
+
fs5.readFileSync(packageJsonPath, "utf-8")
|
|
1376
|
+
);
|
|
1377
|
+
if (!packageJson.name) {
|
|
1378
|
+
throw new Error(`No name found in package.json at ${packageJsonPath}`);
|
|
1379
|
+
}
|
|
1380
|
+
const configMeta = meta ?? { fromApp: packageJson.name };
|
|
1381
|
+
const maybeConfig = findConfig({ dir: packageRoot });
|
|
1382
|
+
if (maybeConfig) {
|
|
1383
|
+
return MicrofrontendsServer.fromFile({
|
|
1384
|
+
filePath: maybeConfig,
|
|
1385
|
+
cookies,
|
|
1386
|
+
meta: configMeta,
|
|
1387
|
+
options
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
const repositoryRoot = findRepositoryRoot();
|
|
1391
|
+
const isMonorepo2 = isMonorepo({ repositoryRoot });
|
|
1392
|
+
if (isMonorepo2) {
|
|
1393
|
+
const defaultPackage = findDefaultMicrofrontendsPackage({
|
|
1394
|
+
repositoryRoot,
|
|
1395
|
+
applicationName: packageJson.name
|
|
1396
|
+
});
|
|
1397
|
+
const maybeConfigFromDefault = findConfig({ dir: defaultPackage });
|
|
1398
|
+
if (maybeConfigFromDefault) {
|
|
1399
|
+
return MicrofrontendsServer.fromFile({
|
|
1400
|
+
filePath: maybeConfigFromDefault,
|
|
1401
|
+
cookies,
|
|
1402
|
+
meta: configMeta,
|
|
1403
|
+
options
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
throw new Error("Unable to infer");
|
|
1408
|
+
} catch (e) {
|
|
1409
|
+
throw new MicrofrontendError(
|
|
1410
|
+
"Unable to infer microfrontends configuration",
|
|
1411
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
/*
|
|
1416
|
+
* Generates a MicrofrontendsServer instance from a file.
|
|
1417
|
+
*/
|
|
1115
1418
|
static fromFile({
|
|
1116
|
-
filePath
|
|
1419
|
+
filePath,
|
|
1420
|
+
cookies,
|
|
1421
|
+
meta,
|
|
1422
|
+
options
|
|
1117
1423
|
}) {
|
|
1118
1424
|
try {
|
|
1119
|
-
const
|
|
1120
|
-
|
|
1121
|
-
|
|
1425
|
+
const configJson = fs5.readFileSync(filePath, "utf-8");
|
|
1426
|
+
const config = MicrofrontendsServer.validate(configJson);
|
|
1427
|
+
if (!isMainConfig(config) && (options == null ? void 0 : options.resolveMainConfig)) {
|
|
1428
|
+
const repositoryRoot = findRepositoryRoot();
|
|
1429
|
+
const isMonorepo2 = isMonorepo({ repositoryRoot });
|
|
1430
|
+
if (isMonorepo2) {
|
|
1431
|
+
const packagePath = findPackagePath({
|
|
1432
|
+
repositoryRoot,
|
|
1433
|
+
name: config.partOf
|
|
1434
|
+
});
|
|
1435
|
+
if (!packagePath) {
|
|
1436
|
+
throw new MicrofrontendError(
|
|
1437
|
+
`Could not find default application "${config.partOf}" in the repository`,
|
|
1438
|
+
{ type: "config", subtype: "not_found" }
|
|
1439
|
+
);
|
|
1440
|
+
}
|
|
1441
|
+
const maybeConfig = findConfig({ dir: packagePath });
|
|
1442
|
+
if (!maybeConfig) {
|
|
1443
|
+
throw new MicrofrontendError(
|
|
1444
|
+
`Could not find microfrontends configuration in ${packagePath}`,
|
|
1445
|
+
{ type: "config", subtype: "not_found" }
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
return MicrofrontendsServer.fromMainConfigFile({
|
|
1449
|
+
filePath: maybeConfig,
|
|
1450
|
+
overrides: cookies ? parseOverrides(cookies) : void 0
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
return new MicrofrontendsServer({
|
|
1455
|
+
config,
|
|
1456
|
+
overrides: cookies ? parseOverrides(cookies) : void 0,
|
|
1457
|
+
meta
|
|
1122
1458
|
});
|
|
1123
1459
|
} catch (e) {
|
|
1124
1460
|
throw MicrofrontendError.handle(e, {
|
|
@@ -1126,20 +1462,41 @@ var MicrofrontendConfig = class extends MicrofrontendConfigCommon {
|
|
|
1126
1462
|
});
|
|
1127
1463
|
}
|
|
1128
1464
|
}
|
|
1129
|
-
|
|
1130
|
-
*
|
|
1465
|
+
/*
|
|
1466
|
+
* Generates a MicrofrontendMainConfig instance from a file.
|
|
1131
1467
|
*/
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1468
|
+
static fromMainConfigFile({
|
|
1469
|
+
filePath,
|
|
1470
|
+
overrides
|
|
1471
|
+
}) {
|
|
1472
|
+
try {
|
|
1473
|
+
const config = fs5.readFileSync(filePath, "utf-8");
|
|
1474
|
+
const validatedConfig = MicrofrontendsServer.validate(config);
|
|
1475
|
+
if (!isMainConfig(validatedConfig)) {
|
|
1476
|
+
throw new MicrofrontendError(
|
|
1477
|
+
`${filePath} is not a main microfrontend config`,
|
|
1478
|
+
{
|
|
1479
|
+
type: "config",
|
|
1480
|
+
subtype: "invalid_main_path"
|
|
1481
|
+
}
|
|
1482
|
+
);
|
|
1483
|
+
}
|
|
1484
|
+
const [defaultApplication] = Object.entries(validatedConfig.applications).filter(([, app]) => isDefaultApp(app)).map(([name]) => name);
|
|
1485
|
+
if (!defaultApplication) {
|
|
1486
|
+
throw new MicrofrontendError(
|
|
1487
|
+
`No default application found. At least one application needs to be the default by omitting routing.`,
|
|
1488
|
+
{ type: "config", subtype: "no_default_application" }
|
|
1489
|
+
);
|
|
1490
|
+
}
|
|
1491
|
+
return new MicrofrontendsServer({
|
|
1492
|
+
config: validatedConfig,
|
|
1493
|
+
overrides,
|
|
1494
|
+
meta: { fromApp: defaultApplication }
|
|
1495
|
+
});
|
|
1496
|
+
} catch (e) {
|
|
1497
|
+
throw MicrofrontendError.handle(e, {
|
|
1498
|
+
fileName: filePath
|
|
1499
|
+
});
|
|
1143
1500
|
}
|
|
1144
1501
|
}
|
|
1145
1502
|
};
|
|
@@ -1155,19 +1512,19 @@ function displayLocalProxyInfo(port) {
|
|
|
1155
1512
|
|
|
1156
1513
|
// src/next/config/transforms/asset-prefix.ts
|
|
1157
1514
|
function transform(args) {
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
if (!((_a = zone.routing) == null ? void 0 : _a.assetPrefix)) {
|
|
1515
|
+
const { next, app } = args;
|
|
1516
|
+
if (app.isDefault()) {
|
|
1161
1517
|
return {
|
|
1162
1518
|
next
|
|
1163
1519
|
};
|
|
1164
1520
|
}
|
|
1165
|
-
if (next.assetPrefix !== void 0 && next.assetPrefix !==
|
|
1166
|
-
|
|
1167
|
-
`"assetPrefix" already set.
|
|
1521
|
+
if (next.assetPrefix !== void 0 && next.assetPrefix !== app.getAssetPrefix()) {
|
|
1522
|
+
console.log(
|
|
1523
|
+
`"assetPrefix" already set. This route must be manually configured in your microfrontend.json file.`
|
|
1168
1524
|
);
|
|
1525
|
+
} else {
|
|
1526
|
+
next.assetPrefix = `/${app.getAssetPrefix()}`;
|
|
1169
1527
|
}
|
|
1170
|
-
next.assetPrefix = `/${zone.routing.assetPrefix}`;
|
|
1171
1528
|
return {
|
|
1172
1529
|
next
|
|
1173
1530
|
};
|
|
@@ -1191,8 +1548,8 @@ function transform2(args) {
|
|
|
1191
1548
|
|
|
1192
1549
|
// src/next/config/transforms/headers.ts
|
|
1193
1550
|
function transform3(args) {
|
|
1194
|
-
const { next,
|
|
1195
|
-
if (
|
|
1551
|
+
const { next, app } = args;
|
|
1552
|
+
if (app.isDefault()) {
|
|
1196
1553
|
return {
|
|
1197
1554
|
next
|
|
1198
1555
|
};
|
|
@@ -1203,7 +1560,11 @@ function transform3(args) {
|
|
|
1203
1560
|
headers: [
|
|
1204
1561
|
{
|
|
1205
1562
|
key: "X-Vercel-Zone",
|
|
1206
|
-
value:
|
|
1563
|
+
value: app.name
|
|
1564
|
+
},
|
|
1565
|
+
{
|
|
1566
|
+
key: "X-Vercel-MFE-App",
|
|
1567
|
+
value: app.name
|
|
1207
1568
|
}
|
|
1208
1569
|
]
|
|
1209
1570
|
},
|
|
@@ -1242,82 +1603,39 @@ function transform3(args) {
|
|
|
1242
1603
|
};
|
|
1243
1604
|
}
|
|
1244
1605
|
|
|
1245
|
-
// src/routing/get-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
if (
|
|
1255
|
-
throw new Error(
|
|
1606
|
+
// src/routing/get-domain-from-environment.ts
|
|
1607
|
+
function getDomainFromEnvironment({
|
|
1608
|
+
app,
|
|
1609
|
+
target
|
|
1610
|
+
}) {
|
|
1611
|
+
var _a;
|
|
1612
|
+
const mfeProjects = JSON.parse(
|
|
1613
|
+
process.env.VERCEL_MICROFRONTENDS_PROJECTS ?? "[]"
|
|
1614
|
+
);
|
|
1615
|
+
if (mfeProjects.length === 0) {
|
|
1616
|
+
throw new Error("Missing related microfrontends project information");
|
|
1256
1617
|
}
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
// biome-ignore lint/style/noNonNullAssertion: Ignored using `--suppress`
|
|
1260
|
-
label: branchUrlParts[0],
|
|
1261
|
-
domain
|
|
1262
|
-
};
|
|
1263
|
-
}
|
|
1264
|
-
function getDomainSuffix(branchUrl, vercelUrl) {
|
|
1265
|
-
const branchLabelParts = parseBranchUrl(branchUrl).label.split("-");
|
|
1266
|
-
const vercelUrlLabelParts = parseBranchUrl(vercelUrl).label.split("-");
|
|
1267
|
-
const suffixParts = [];
|
|
1268
|
-
for (let i = 1; i < branchLabelParts.length; i++) {
|
|
1269
|
-
if (branchLabelParts.at(-1 * i) === vercelUrlLabelParts.at(-1 * i)) {
|
|
1270
|
-
suffixParts.push(branchLabelParts.at(-1 * i) ?? "");
|
|
1271
|
-
}
|
|
1618
|
+
if (!((_a = app.vercel) == null ? void 0 : _a.projectId)) {
|
|
1619
|
+
throw new Error(`Missing applications[${app.name}].vercel.projectId`);
|
|
1272
1620
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1621
|
+
const vercelProject = mfeProjects.find(
|
|
1622
|
+
(p) => {
|
|
1623
|
+
var _a2;
|
|
1624
|
+
return p.project.id === ((_a2 = app.vercel) == null ? void 0 : _a2.projectId);
|
|
1625
|
+
}
|
|
1626
|
+
);
|
|
1627
|
+
if (!vercelProject) {
|
|
1279
1628
|
throw new Error(
|
|
1280
|
-
`Missing
|
|
1629
|
+
`Missing related microfrontends project information for application "${app.name}"`
|
|
1281
1630
|
);
|
|
1282
1631
|
}
|
|
1283
|
-
const
|
|
1284
|
-
if (
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
const gitBranch = `git-${VERCEL_GIT_COMMIT_REF.toLocaleLowerCase()}`;
|
|
1289
|
-
const gitBranchForHash = `git-${VERCEL_GIT_COMMIT_REF}`;
|
|
1290
|
-
const urlSafeBranch = makeUrlSafe(gitBranch);
|
|
1291
|
-
const urlSafeProjectName = makeUrlSafe(targetVercelProjectName);
|
|
1292
|
-
const maxLabelLength = getMaxLabelLength(domain);
|
|
1293
|
-
const label = [urlSafeProjectName, urlSafeBranch, stagingSuffix].filter(Boolean).join("-");
|
|
1294
|
-
if (label.length > maxLabelLength) {
|
|
1295
|
-
let newLabel = makeUrlSafe(stagingSuffix).slice(0, maxLabelLength);
|
|
1296
|
-
const hash = createHash("sha256").update(`${gitBranchForHash}${targetVercelProjectName}`).digest("hex").slice(0, 6);
|
|
1297
|
-
newLabel = [hash, newLabel].filter(Boolean).join("-");
|
|
1298
|
-
const projectNamePart = makeUrlSafe(
|
|
1299
|
-
urlSafeProjectName.slice(0, maxLabelLength - newLabel.length - 1 - 4)
|
|
1300
|
-
);
|
|
1301
|
-
const branchPart = makeUrlSafe(
|
|
1302
|
-
urlSafeBranch.slice(
|
|
1303
|
-
0,
|
|
1304
|
-
Math.max(
|
|
1305
|
-
0,
|
|
1306
|
-
maxLabelLength - (newLabel.length + projectNamePart.length) - 2
|
|
1307
|
-
)
|
|
1308
|
-
)
|
|
1309
|
-
);
|
|
1310
|
-
if (branchPart.length >= 3) {
|
|
1311
|
-
newLabel = [branchPart, newLabel].filter(Boolean).join("-");
|
|
1312
|
-
}
|
|
1313
|
-
if (projectNamePart) {
|
|
1314
|
-
newLabel = [projectNamePart, newLabel].filter(Boolean).join("-");
|
|
1315
|
-
}
|
|
1316
|
-
return `https://${newLabel}.${domain}`;
|
|
1317
|
-
}
|
|
1318
|
-
return `https://${label}.${domain}`;
|
|
1632
|
+
const domain = target === "preview" && vercelProject.preview.branch ? vercelProject.preview.branch : vercelProject.production.alias ?? vercelProject.production.url;
|
|
1633
|
+
if (!domain) {
|
|
1634
|
+
throw new Error(
|
|
1635
|
+
`Missing domain for target "${target}" in application "${app.name}"`
|
|
1636
|
+
);
|
|
1319
1637
|
}
|
|
1320
|
-
return
|
|
1638
|
+
return domain.startsWith("https://") ? domain : `https://${domain}`;
|
|
1321
1639
|
}
|
|
1322
1640
|
|
|
1323
1641
|
// src/routing/get-domain-for-current-environment.ts
|
|
@@ -1333,34 +1651,45 @@ ${line}
|
|
|
1333
1651
|
`);
|
|
1334
1652
|
}
|
|
1335
1653
|
}
|
|
1336
|
-
function
|
|
1654
|
+
function getCurrentEnvironment() {
|
|
1655
|
+
const isDevelopment = !process.env.VERCEL_ENV || process.env.VERCEL_ENV === "development";
|
|
1656
|
+
const isPreview = process.env.VERCEL_ENV === "preview";
|
|
1657
|
+
const isProduction2 = process.env.VERCEL_ENV === "production";
|
|
1658
|
+
if (isDevelopment) {
|
|
1659
|
+
return { group: "development" };
|
|
1660
|
+
} else if (isProduction2) {
|
|
1661
|
+
return { group: "production" };
|
|
1662
|
+
} else if (isPreview) {
|
|
1663
|
+
return { group: "preview" };
|
|
1664
|
+
}
|
|
1665
|
+
return { group: "custom", name: process.env.VERCEL_ENV };
|
|
1666
|
+
}
|
|
1667
|
+
function getDomainForCurrentEnvironment(config, appName, opts = {}) {
|
|
1337
1668
|
var _a;
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
return domain;
|
|
1350
|
-
} else if (process.env.VERCEL_ENV === "preview") {
|
|
1351
|
-
const MFE_PREVIEW_DOMAINS = JSON.parse(
|
|
1352
|
-
process.env.MFE_PREVIEW_DOMAINS ?? "{}"
|
|
1353
|
-
);
|
|
1354
|
-
if (MFE_PREVIEW_DOMAINS[zoneName]) {
|
|
1355
|
-
debugDomains(zoneName, "preview", MFE_PREVIEW_DOMAINS[zoneName]);
|
|
1356
|
-
return MFE_PREVIEW_DOMAINS[zoneName];
|
|
1669
|
+
const app = config.getApplication(appName);
|
|
1670
|
+
if (!opts.ignoreOverride && ((_a = app.overrides) == null ? void 0 : _a.environment)) {
|
|
1671
|
+
return app.overrides.environment.toString();
|
|
1672
|
+
}
|
|
1673
|
+
const { group } = getCurrentEnvironment();
|
|
1674
|
+
const productionHost = config.getDefaultApplication().production.toString();
|
|
1675
|
+
switch (group) {
|
|
1676
|
+
case "development": {
|
|
1677
|
+
const domain = ["test", "development"].includes(process.env.NODE_ENV) ? app.development.local.toString() : productionHost;
|
|
1678
|
+
debugDomains(appName, "development", domain);
|
|
1679
|
+
return domain;
|
|
1357
1680
|
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1681
|
+
case "preview": {
|
|
1682
|
+
return getDomainFromEnvironment({ app, target: "preview" });
|
|
1683
|
+
}
|
|
1684
|
+
case "production": {
|
|
1685
|
+
return getDomainFromEnvironment({ app, target: "production" });
|
|
1686
|
+
}
|
|
1687
|
+
case "custom":
|
|
1688
|
+
console.warn(
|
|
1689
|
+
`Custom environments are not supported in getDomainForCurrentEnvironment`
|
|
1690
|
+
);
|
|
1691
|
+
return productionHost;
|
|
1361
1692
|
}
|
|
1362
|
-
debugDomains(zoneName, process.env.VERCEL_ENV, zone.production.toString());
|
|
1363
|
-
return zone.production.toString();
|
|
1364
1693
|
}
|
|
1365
1694
|
|
|
1366
1695
|
// src/next/config/transforms/rewrites.ts
|
|
@@ -1382,11 +1711,11 @@ ${table}
|
|
|
1382
1711
|
`);
|
|
1383
1712
|
}
|
|
1384
1713
|
}
|
|
1385
|
-
function pathToRewrites(
|
|
1714
|
+
function pathToRewrites(path5) {
|
|
1386
1715
|
var _a;
|
|
1387
1716
|
const regex = /(?<base>^.+)\/:.+\*$/;
|
|
1388
|
-
const match = regex.exec(
|
|
1389
|
-
const paths = [
|
|
1717
|
+
const match = regex.exec(path5);
|
|
1718
|
+
const paths = [path5];
|
|
1390
1719
|
if ((_a = match == null ? void 0 : match.groups) == null ? void 0 : _a.base) {
|
|
1391
1720
|
paths.unshift(match.groups.base);
|
|
1392
1721
|
}
|
|
@@ -1415,42 +1744,39 @@ function rewritesMapToArr(rewrites) {
|
|
|
1415
1744
|
});
|
|
1416
1745
|
}
|
|
1417
1746
|
function transform4(args) {
|
|
1418
|
-
const { next, microfrontend,
|
|
1747
|
+
const { next, microfrontend, app } = args;
|
|
1419
1748
|
const buildBeforeFiles = () => {
|
|
1420
|
-
var _a, _b, _c, _d;
|
|
1421
1749
|
const rewrites = /* @__PURE__ */ new Map();
|
|
1422
|
-
if ((
|
|
1423
|
-
rewrites.set(`/${
|
|
1750
|
+
if (!app.isDefault()) {
|
|
1751
|
+
rewrites.set(`/${app.getAssetPrefix()}/_next/:path+`, {
|
|
1424
1752
|
destination: {
|
|
1425
1753
|
pathname: `/_next/:path+`
|
|
1426
1754
|
}
|
|
1427
1755
|
});
|
|
1428
|
-
|
|
1429
|
-
|
|
1756
|
+
rewrites.set(`/${app.getAssetPrefix()}/.well-known/vercel/flags`, {
|
|
1757
|
+
destination: {
|
|
1758
|
+
pathname: `/.well-known/vercel/flags`
|
|
1759
|
+
}
|
|
1760
|
+
});
|
|
1761
|
+
if (process.env.VERCEL_MICROFRONTENDS_CONSOLIDATE_SPEED_INSIGHTS === "1") {
|
|
1762
|
+
rewrites.set(`/${app.getAssetPrefix()}/_vercel/:path*`, {
|
|
1430
1763
|
destination: { pathname: "/_vercel/:path*" }
|
|
1431
1764
|
});
|
|
1432
1765
|
}
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
domain,
|
|
1448
|
-
pathname: `/${z.routing.assetPrefix}/:path+`
|
|
1449
|
-
}
|
|
1450
|
-
});
|
|
1451
|
-
}
|
|
1452
|
-
for (const group of routing.matches) {
|
|
1453
|
-
if ((_d = group.options) == null ? void 0 : _d.flag) {
|
|
1766
|
+
} else if (microfrontend instanceof MicrofrontendMainConfig) {
|
|
1767
|
+
for (const [_, a] of Object.entries(
|
|
1768
|
+
microfrontend.getChildApplications()
|
|
1769
|
+
)) {
|
|
1770
|
+
const { routing } = a;
|
|
1771
|
+
const domain = getDomainForCurrentEnvironment(microfrontend, a.name);
|
|
1772
|
+
rewrites.set(`/${a.getAssetPrefix()}/:path+`, {
|
|
1773
|
+
destination: {
|
|
1774
|
+
domain,
|
|
1775
|
+
pathname: `/${a.getAssetPrefix()}/:path+`
|
|
1776
|
+
}
|
|
1777
|
+
});
|
|
1778
|
+
for (const group of routing) {
|
|
1779
|
+
if (group.flag) {
|
|
1454
1780
|
continue;
|
|
1455
1781
|
} else {
|
|
1456
1782
|
for (const source of group.paths) {
|
|
@@ -1464,7 +1790,6 @@ function transform4(args) {
|
|
|
1464
1790
|
}
|
|
1465
1791
|
}
|
|
1466
1792
|
}
|
|
1467
|
-
} else {
|
|
1468
1793
|
}
|
|
1469
1794
|
return rewritesMapToArr(rewrites);
|
|
1470
1795
|
};
|
|
@@ -1501,17 +1826,44 @@ function transform4(args) {
|
|
|
1501
1826
|
}
|
|
1502
1827
|
|
|
1503
1828
|
// src/next/config/transforms/server-actions.ts
|
|
1829
|
+
function debugRewrites2(allowedOrigins) {
|
|
1830
|
+
if (process.env.MFE_DEBUG === "true" && allowedOrigins) {
|
|
1831
|
+
const indent = " ".repeat(4);
|
|
1832
|
+
const header = "server actions allowed origins";
|
|
1833
|
+
const separator = "\u23AF".repeat(header.length);
|
|
1834
|
+
const maxSourceLength = Math.max(
|
|
1835
|
+
...allowedOrigins.map((key) => key.length)
|
|
1836
|
+
);
|
|
1837
|
+
const table = allowedOrigins.map((origin, idx) => {
|
|
1838
|
+
const paddedSource = origin.padEnd(maxSourceLength);
|
|
1839
|
+
return `${indent} ${idx + 1}. ${paddedSource}`;
|
|
1840
|
+
}).join("\n");
|
|
1841
|
+
console.log(`${indent}${header}
|
|
1842
|
+
${indent}${separator}
|
|
1843
|
+
${table}
|
|
1844
|
+
`);
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1504
1847
|
var formatDomainForServerAction = (domain) => domain.replace(/https?:\/\//, "");
|
|
1505
1848
|
function transform5(args) {
|
|
1506
|
-
var _a;
|
|
1507
|
-
const { next,
|
|
1508
|
-
|
|
1849
|
+
var _a, _b;
|
|
1850
|
+
const { next, app, microfrontend } = args;
|
|
1851
|
+
if (microfrontend instanceof MicrofrontendChildConfig) {
|
|
1852
|
+
console.warn(
|
|
1853
|
+
"server actions transform requires the full config - skipping"
|
|
1854
|
+
);
|
|
1855
|
+
return {
|
|
1856
|
+
next
|
|
1857
|
+
};
|
|
1858
|
+
}
|
|
1859
|
+
const defaultApplication = microfrontend.getDefaultApplication();
|
|
1860
|
+
const appsToAllow = [
|
|
1509
1861
|
// this zone - this is included by default unless allowedOrigins is overridden (which we are)
|
|
1510
1862
|
// so we re-add it here.
|
|
1511
|
-
|
|
1863
|
+
app,
|
|
1512
1864
|
// this is the default zone for the microfrontend. Allow child zones to call server actions
|
|
1513
1865
|
// that are in the default zone.
|
|
1514
|
-
|
|
1866
|
+
defaultApplication
|
|
1515
1867
|
];
|
|
1516
1868
|
const existingServerActionConfig = (_a = next.experimental) == null ? void 0 : _a.serverActions;
|
|
1517
1869
|
next.experimental = {
|
|
@@ -1520,15 +1872,23 @@ function transform5(args) {
|
|
|
1520
1872
|
...existingServerActionConfig,
|
|
1521
1873
|
allowedOrigins: Array.from(
|
|
1522
1874
|
/* @__PURE__ */ new Set([
|
|
1875
|
+
// existing
|
|
1523
1876
|
...(existingServerActionConfig == null ? void 0 : existingServerActionConfig.allowedOrigins) ?? [],
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1877
|
+
// this deployments host
|
|
1878
|
+
...process.env.VERCEL_URL ? [formatDomainForServerAction(process.env.VERCEL_URL)] : [],
|
|
1879
|
+
// default application host
|
|
1880
|
+
formatDomainForServerAction(defaultApplication.production.toString()),
|
|
1881
|
+
// environment specific microfrontend hosts
|
|
1882
|
+
...appsToAllow.flatMap((a) => [
|
|
1883
|
+
formatDomainForServerAction(
|
|
1884
|
+
getDomainForCurrentEnvironment(microfrontend, a.name)
|
|
1885
|
+
)
|
|
1527
1886
|
])
|
|
1528
1887
|
])
|
|
1529
1888
|
)
|
|
1530
1889
|
}
|
|
1531
1890
|
};
|
|
1891
|
+
debugRewrites2((_b = next.experimental.serverActions) == null ? void 0 : _b.allowedOrigins);
|
|
1532
1892
|
return {
|
|
1533
1893
|
next
|
|
1534
1894
|
};
|
|
@@ -1537,14 +1897,6 @@ function transform5(args) {
|
|
|
1537
1897
|
// src/next/config/transforms/webpack.ts
|
|
1538
1898
|
function transform6(args) {
|
|
1539
1899
|
const { next, microfrontend } = args;
|
|
1540
|
-
const previewDomains = process.env.VERCEL_ENV === "preview" ? microfrontend.getAllApplications().reduce(
|
|
1541
|
-
(obj, app) => {
|
|
1542
|
-
obj[app.name] = getPreviewDomain(app);
|
|
1543
|
-
return obj;
|
|
1544
|
-
},
|
|
1545
|
-
// eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter -- needed to satisfy TSC
|
|
1546
|
-
{}
|
|
1547
|
-
) : {};
|
|
1548
1900
|
const configWithWebpack = {
|
|
1549
1901
|
...next,
|
|
1550
1902
|
webpack(cfg, context) {
|
|
@@ -1553,8 +1905,7 @@ function transform6(args) {
|
|
|
1553
1905
|
if (isServer || nextRuntime === "edge") {
|
|
1554
1906
|
config.plugins.push(
|
|
1555
1907
|
new wpFromNext.EnvironmentPlugin({
|
|
1556
|
-
MFE_CONFIG: JSON.stringify(microfrontend.serialize())
|
|
1557
|
-
MFE_PREVIEW_DOMAINS: JSON.stringify(previewDomains)
|
|
1908
|
+
MFE_CONFIG: JSON.stringify(microfrontend.serialize())
|
|
1558
1909
|
})
|
|
1559
1910
|
);
|
|
1560
1911
|
}
|
|
@@ -1594,21 +1945,6 @@ var transforms = {
|
|
|
1594
1945
|
webpack: transform6
|
|
1595
1946
|
};
|
|
1596
1947
|
|
|
1597
|
-
// src/config/client/client-config.ts
|
|
1598
|
-
function getConfigForClient(config) {
|
|
1599
|
-
return {
|
|
1600
|
-
applications: Object.fromEntries(
|
|
1601
|
-
Object.entries(config.applications).map(([name, application]) => [
|
|
1602
|
-
name,
|
|
1603
|
-
{
|
|
1604
|
-
default: application.default,
|
|
1605
|
-
routing: application.routing
|
|
1606
|
-
}
|
|
1607
|
-
])
|
|
1608
|
-
)
|
|
1609
|
-
};
|
|
1610
|
-
}
|
|
1611
|
-
|
|
1612
1948
|
// src/next/config/env.ts
|
|
1613
1949
|
function debugEnv(env) {
|
|
1614
1950
|
if (process.env.MFE_DEBUG === "true") {
|
|
@@ -1627,32 +1963,18 @@ ${table}
|
|
|
1627
1963
|
}
|
|
1628
1964
|
}
|
|
1629
1965
|
function setEnvironment({
|
|
1630
|
-
|
|
1631
|
-
|
|
1966
|
+
app,
|
|
1967
|
+
microfrontends
|
|
1632
1968
|
}) {
|
|
1633
|
-
var _a, _b, _c, _d;
|
|
1634
|
-
const previewDomains = process.env.VERCEL_ENV === "preview" ? config.getAllApplications().reduce(
|
|
1635
|
-
(obj, app) => {
|
|
1636
|
-
obj[app.name] = getPreviewDomain(app);
|
|
1637
|
-
return obj;
|
|
1638
|
-
},
|
|
1639
|
-
// eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter -- needed to satisfy TSC
|
|
1640
|
-
{}
|
|
1641
|
-
) : {};
|
|
1642
1969
|
const clientEnvs = {
|
|
1643
|
-
NEXT_PUBLIC_MFE_CURRENT_APPLICATION:
|
|
1970
|
+
NEXT_PUBLIC_MFE_CURRENT_APPLICATION: app.name,
|
|
1644
1971
|
NEXT_PUBLIC_MFE_CLIENT_CONFIG: JSON.stringify(
|
|
1645
|
-
|
|
1646
|
-
)
|
|
1647
|
-
...((_a = zone.vercel) == null ? void 0 : _a.routeSpeedInsightsToDefaultZone) && ((_b = zone.routing) == null ? void 0 : _b.assetPrefix) ? {} : {
|
|
1648
|
-
NEXT_PUBLIC_SPEED_INSIGHTS_BASEPATH: (_c = zone.routing) == null ? void 0 : _c.assetPrefix,
|
|
1649
|
-
NEXT_PUBLIC_WEB_ANALYTICS_BASEPATH: (_d = zone.routing) == null ? void 0 : _d.assetPrefix
|
|
1650
|
-
}
|
|
1972
|
+
microfrontends.config.toClientConfig().serialize()
|
|
1973
|
+
)
|
|
1651
1974
|
};
|
|
1652
1975
|
const serverEnvs = {
|
|
1653
|
-
MFE_CURRENT_APPLICATION:
|
|
1654
|
-
|
|
1655
|
-
MFE_CONFIG: JSON.stringify(config.getConfig())
|
|
1976
|
+
MFE_CURRENT_APPLICATION: app.name,
|
|
1977
|
+
MFE_CONFIG: JSON.stringify(microfrontends.config.getConfig())
|
|
1656
1978
|
};
|
|
1657
1979
|
const allEnvs = { ...clientEnvs, ...serverEnvs };
|
|
1658
1980
|
for (const [key, value] of Object.entries(allEnvs)) {
|
|
@@ -1671,37 +1993,12 @@ function isProduction(opts) {
|
|
|
1671
1993
|
}
|
|
1672
1994
|
return process.env.VERCEL_ENV === "production";
|
|
1673
1995
|
}
|
|
1674
|
-
function getConfigPath(opts) {
|
|
1675
|
-
var _a;
|
|
1676
|
-
if (opts == null ? void 0 : opts.configPath) {
|
|
1677
|
-
return { configPath: opts.configPath };
|
|
1678
|
-
}
|
|
1679
|
-
try {
|
|
1680
|
-
const vercelJsonString = fs3.readFileSync("./vercel.json", "utf-8");
|
|
1681
|
-
const vercelJson = JSON.parse(vercelJsonString);
|
|
1682
|
-
if (!((_a = vercelJson.microFrontends) == null ? void 0 : _a.config)) {
|
|
1683
|
-
throw new MicrofrontendError(
|
|
1684
|
-
`vercel.json file missing required field "microFrontends.config"`,
|
|
1685
|
-
{
|
|
1686
|
-
type: "vercelJson",
|
|
1687
|
-
subtype: "missing_field_microFrontend_config_path",
|
|
1688
|
-
source: "@vercel/microfrontends/next"
|
|
1689
|
-
}
|
|
1690
|
-
);
|
|
1691
|
-
}
|
|
1692
|
-
return { configPath: vercelJson.microFrontends.config };
|
|
1693
|
-
} catch (err) {
|
|
1694
|
-
throw MicrofrontendError.handle(err, {
|
|
1695
|
-
fileName: "vercel.json"
|
|
1696
|
-
});
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
1699
1996
|
function getApplicationContext(opts) {
|
|
1700
1997
|
if (opts == null ? void 0 : opts.appName) {
|
|
1701
1998
|
return { name: opts.appName };
|
|
1702
1999
|
}
|
|
1703
2000
|
try {
|
|
1704
|
-
const packageJsonString =
|
|
2001
|
+
const packageJsonString = fs6.readFileSync("./package.json", "utf-8");
|
|
1705
2002
|
const packageJson = JSON.parse(packageJsonString);
|
|
1706
2003
|
if (!packageJson.name) {
|
|
1707
2004
|
throw new MicrofrontendError(
|
|
@@ -1725,13 +2022,15 @@ function withMicrofrontends(nextConfig, opts) {
|
|
|
1725
2022
|
if (opts == null ? void 0 : opts.debug) {
|
|
1726
2023
|
process.env.MFE_DEBUG = "true";
|
|
1727
2024
|
}
|
|
1728
|
-
const { name } = getApplicationContext(opts);
|
|
1729
|
-
const
|
|
1730
|
-
|
|
1731
|
-
|
|
2025
|
+
const { name: fromApp } = getApplicationContext(opts);
|
|
2026
|
+
const microfrontends = MicrofrontendsServer.infer({
|
|
2027
|
+
filePath: opts == null ? void 0 : opts.configPath,
|
|
2028
|
+
meta: {
|
|
2029
|
+
fromApp
|
|
2030
|
+
}
|
|
1732
2031
|
});
|
|
1733
|
-
const
|
|
1734
|
-
setEnvironment({
|
|
2032
|
+
const app = microfrontends.config.getApplication(fromApp);
|
|
2033
|
+
setEnvironment({ app, microfrontends });
|
|
1735
2034
|
let next = { ...nextConfig };
|
|
1736
2035
|
for (const [key, transform7] of typedEntries(transforms)) {
|
|
1737
2036
|
if ((_a = opts == null ? void 0 : opts.skipTransforms) == null ? void 0 : _a.includes(key)) {
|
|
@@ -1740,9 +2039,9 @@ function withMicrofrontends(nextConfig, opts) {
|
|
|
1740
2039
|
}
|
|
1741
2040
|
try {
|
|
1742
2041
|
const transformedConfig = transform7({
|
|
1743
|
-
|
|
2042
|
+
app,
|
|
1744
2043
|
next,
|
|
1745
|
-
microfrontend:
|
|
2044
|
+
microfrontend: microfrontends.config,
|
|
1746
2045
|
opts: {
|
|
1747
2046
|
isProduction: isProduction(opts)
|
|
1748
2047
|
}
|
|
@@ -1752,9 +2051,9 @@ function withMicrofrontends(nextConfig, opts) {
|
|
|
1752
2051
|
console.error("Error transforming next config", e);
|
|
1753
2052
|
}
|
|
1754
2053
|
}
|
|
1755
|
-
displayLocalProxyInfo(
|
|
2054
|
+
displayLocalProxyInfo(microfrontends.config.getLocalProxyPort());
|
|
1756
2055
|
if (isVercel()) {
|
|
1757
|
-
|
|
2056
|
+
microfrontends.writeConfig();
|
|
1758
2057
|
}
|
|
1759
2058
|
return next;
|
|
1760
2059
|
}
|