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