@vercel/microfrontends 2.2.1 → 2.2.2
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/CHANGELOG.md +19 -0
- package/cli/index.cjs +0 -1
- package/dist/bin/cli.cjs +483 -394
- package/dist/config.cjs +191 -169
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.ts +3 -2
- package/dist/config.js +192 -170
- package/dist/config.js.map +1 -1
- package/dist/experimental/sveltekit.cjs +583 -511
- package/dist/experimental/sveltekit.cjs.map +1 -1
- package/dist/experimental/sveltekit.js +589 -517
- package/dist/experimental/sveltekit.js.map +1 -1
- package/dist/experimental/vite.cjs +605 -533
- package/dist/experimental/vite.cjs.map +1 -1
- package/dist/experimental/vite.js +614 -542
- package/dist/experimental/vite.js.map +1 -1
- package/dist/microfrontends/server.cjs +601 -529
- package/dist/microfrontends/server.cjs.map +1 -1
- package/dist/microfrontends/server.d.ts +2 -2
- package/dist/microfrontends/server.js +607 -535
- package/dist/microfrontends/server.js.map +1 -1
- package/dist/microfrontends/utils.cjs +101 -50
- package/dist/microfrontends/utils.cjs.map +1 -1
- package/dist/microfrontends/utils.d.ts +4 -4
- package/dist/microfrontends/utils.js +102 -51
- package/dist/microfrontends/utils.js.map +1 -1
- package/dist/next/client.cjs +1 -1
- package/dist/next/client.cjs.map +1 -1
- package/dist/next/client.d.ts +8 -8
- package/dist/next/client.js +1 -1
- package/dist/next/client.js.map +1 -1
- package/dist/next/config.cjs +723 -647
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.js +720 -644
- package/dist/next/config.js.map +1 -1
- package/dist/next/middleware.cjs +244 -222
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.js +245 -223
- package/dist/next/middleware.js.map +1 -1
- package/dist/next/testing.cjs +192 -170
- package/dist/next/testing.cjs.map +1 -1
- package/dist/next/testing.d.ts +1 -1
- package/dist/next/testing.js +193 -171
- package/dist/next/testing.js.map +1 -1
- package/dist/overrides.cjs +5 -5
- package/dist/overrides.cjs.map +1 -1
- package/dist/overrides.d.ts +9 -9
- package/dist/overrides.js +5 -5
- package/dist/overrides.js.map +1 -1
- package/dist/utils/mfe-port.cjs +620 -533
- package/dist/utils/mfe-port.cjs.map +1 -1
- package/dist/utils/mfe-port.d.ts +9 -1
- package/dist/utils/mfe-port.js +632 -546
- package/dist/utils/mfe-port.js.map +1 -1
- package/dist/validation.cjs +8 -24
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.js +8 -24
- package/dist/validation.js.map +1 -1
- package/package.json +4 -6
package/dist/utils/mfe-port.cjs
CHANGED
|
@@ -30,48 +30,38 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/utils/mfe-port.ts
|
|
31
31
|
var mfe_port_exports = {};
|
|
32
32
|
__export(mfe_port_exports, {
|
|
33
|
+
MFE_APP_PORT_ENV: () => MFE_APP_PORT_ENV2,
|
|
33
34
|
mfePort: () => mfePort
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(mfe_port_exports);
|
|
36
|
-
var import_node_path9 = __toESM(require("path"), 1);
|
|
37
37
|
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
38
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
38
39
|
|
|
39
40
|
// src/config/microfrontends/server/index.ts
|
|
40
41
|
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
41
42
|
var import_node_path8 = require("path");
|
|
42
43
|
|
|
43
|
-
// src/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
function isOverrideCookie(cookie) {
|
|
49
|
-
return Boolean(cookie.name?.startsWith(OVERRIDES_COOKIE_PREFIX));
|
|
44
|
+
// src/bin/logger.ts
|
|
45
|
+
function debug(...args) {
|
|
46
|
+
if (process.env.MFE_DEBUG) {
|
|
47
|
+
console.log(...args);
|
|
48
|
+
}
|
|
50
49
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
function getOverrideFromCookie(cookie) {
|
|
54
|
-
if (!isOverrideCookie(cookie) || !cookie.value)
|
|
55
|
-
return;
|
|
56
|
-
return {
|
|
57
|
-
application: cookie.name.replace(OVERRIDES_ENV_COOKIE_PREFIX, ""),
|
|
58
|
-
host: cookie.value
|
|
59
|
-
};
|
|
50
|
+
function info(...args) {
|
|
51
|
+
console.log(...args);
|
|
60
52
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const override = getOverrideFromCookie(cookie);
|
|
67
|
-
if (!override)
|
|
68
|
-
return;
|
|
69
|
-
overridesConfig.applications[override.application] = {
|
|
70
|
-
environment: { host: override.host }
|
|
71
|
-
};
|
|
72
|
-
});
|
|
73
|
-
return overridesConfig;
|
|
53
|
+
function warn(...args) {
|
|
54
|
+
console.warn(...args);
|
|
55
|
+
}
|
|
56
|
+
function error(...args) {
|
|
57
|
+
console.error(...args);
|
|
74
58
|
}
|
|
59
|
+
var logger = {
|
|
60
|
+
debug,
|
|
61
|
+
info,
|
|
62
|
+
warn,
|
|
63
|
+
error
|
|
64
|
+
};
|
|
75
65
|
|
|
76
66
|
// src/config/errors.ts
|
|
77
67
|
var MicrofrontendError = class extends Error {
|
|
@@ -165,296 +155,47 @@ var MicrofrontendError = class extends Error {
|
|
|
165
155
|
}
|
|
166
156
|
};
|
|
167
157
|
|
|
168
|
-
// src/config/microfrontends-config/
|
|
169
|
-
function getConfigStringFromEnv() {
|
|
170
|
-
const config = process.env.MFE_CONFIG;
|
|
171
|
-
if (!config) {
|
|
172
|
-
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
173
|
-
type: "config",
|
|
174
|
-
subtype: "not_found_in_env"
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
return config;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// src/config/schema/utils/is-default-app.ts
|
|
181
|
-
function isDefaultApp(a) {
|
|
182
|
-
return !("routing" in a);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// src/config/microfrontends/utils/find-repository-root.ts
|
|
186
|
-
var import_node_fs = __toESM(require("fs"), 1);
|
|
187
|
-
var import_node_path = __toESM(require("path"), 1);
|
|
188
|
-
var GIT_DIRECTORY = ".git";
|
|
189
|
-
function hasGitDirectory(dir) {
|
|
190
|
-
const gitPath = import_node_path.default.join(dir, GIT_DIRECTORY);
|
|
191
|
-
return import_node_fs.default.existsSync(gitPath) && import_node_fs.default.statSync(gitPath).isDirectory();
|
|
192
|
-
}
|
|
193
|
-
function hasPnpmWorkspaces(dir) {
|
|
194
|
-
return import_node_fs.default.existsSync(import_node_path.default.join(dir, "pnpm-workspace.yaml"));
|
|
195
|
-
}
|
|
196
|
-
function hasPackageJson(dir) {
|
|
197
|
-
return import_node_fs.default.existsSync(import_node_path.default.join(dir, "package.json"));
|
|
198
|
-
}
|
|
199
|
-
function findRepositoryRoot(startDir) {
|
|
200
|
-
if (process.env.NX_WORKSPACE_ROOT) {
|
|
201
|
-
return process.env.NX_WORKSPACE_ROOT;
|
|
202
|
-
}
|
|
203
|
-
let currentDir = startDir || process.cwd();
|
|
204
|
-
let lastPackageJsonDir = null;
|
|
205
|
-
while (currentDir !== import_node_path.default.parse(currentDir).root) {
|
|
206
|
-
if (hasGitDirectory(currentDir) || hasPnpmWorkspaces(currentDir)) {
|
|
207
|
-
return currentDir;
|
|
208
|
-
}
|
|
209
|
-
if (hasPackageJson(currentDir)) {
|
|
210
|
-
lastPackageJsonDir = currentDir;
|
|
211
|
-
}
|
|
212
|
-
currentDir = import_node_path.default.dirname(currentDir);
|
|
213
|
-
}
|
|
214
|
-
if (lastPackageJsonDir) {
|
|
215
|
-
return lastPackageJsonDir;
|
|
216
|
-
}
|
|
217
|
-
throw new Error(
|
|
218
|
-
`Could not find the root of the repository for ${startDir}. Please ensure that the directory is part of a Git repository. If you suspect that this should work, please file an issue to the Vercel team.`
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
223
|
-
var import_node_path2 = require("path");
|
|
224
|
-
var import_node_fs2 = require("fs");
|
|
158
|
+
// src/config/microfrontends-config/isomorphic/index.ts
|
|
225
159
|
var import_jsonc_parser = require("jsonc-parser");
|
|
226
|
-
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
227
|
-
|
|
228
|
-
// src/bin/logger.ts
|
|
229
|
-
function debug(...args) {
|
|
230
|
-
if (process.env.MFE_DEBUG) {
|
|
231
|
-
console.log(...args);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
function info(...args) {
|
|
235
|
-
console.log(...args);
|
|
236
|
-
}
|
|
237
|
-
function warn(...args) {
|
|
238
|
-
console.warn(...args);
|
|
239
|
-
}
|
|
240
|
-
function error(...args) {
|
|
241
|
-
console.error(...args);
|
|
242
|
-
}
|
|
243
|
-
var logger = {
|
|
244
|
-
debug,
|
|
245
|
-
info,
|
|
246
|
-
warn,
|
|
247
|
-
error
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
// src/config/microfrontends/utils/get-config-file-name.ts
|
|
251
|
-
var DEFAULT_CONFIGURATION_FILENAMES = [
|
|
252
|
-
"microfrontends.json",
|
|
253
|
-
"microfrontends.jsonc"
|
|
254
|
-
];
|
|
255
|
-
function getPossibleConfigurationFilenames({
|
|
256
|
-
customConfigFilename
|
|
257
|
-
}) {
|
|
258
|
-
if (customConfigFilename) {
|
|
259
|
-
if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
|
|
260
|
-
throw new Error(
|
|
261
|
-
`Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}. The file name must end with '.json' or '.jsonc'. It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
return Array.from(
|
|
265
|
-
/* @__PURE__ */ new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES])
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
return DEFAULT_CONFIGURATION_FILENAMES;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
272
|
-
var configCache = {};
|
|
273
|
-
function findPackageWithMicrofrontendsConfig({
|
|
274
|
-
repositoryRoot,
|
|
275
|
-
applicationContext,
|
|
276
|
-
customConfigFilename
|
|
277
|
-
}) {
|
|
278
|
-
const applicationName = applicationContext.name;
|
|
279
|
-
logger.debug(
|
|
280
|
-
"[MFE Config] Searching repository for configs containing application:",
|
|
281
|
-
applicationName
|
|
282
|
-
);
|
|
283
|
-
try {
|
|
284
|
-
const microfrontendsJsonPaths = import_fast_glob.default.globSync(
|
|
285
|
-
`**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
|
|
286
|
-
{
|
|
287
|
-
cwd: repositoryRoot,
|
|
288
|
-
absolute: true,
|
|
289
|
-
onlyFiles: true,
|
|
290
|
-
followSymbolicLinks: false,
|
|
291
|
-
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
292
|
-
}
|
|
293
|
-
);
|
|
294
|
-
logger.debug(
|
|
295
|
-
"[MFE Config] Found",
|
|
296
|
-
microfrontendsJsonPaths.length,
|
|
297
|
-
"config file(s) in repository"
|
|
298
|
-
);
|
|
299
|
-
const matchingPaths = [];
|
|
300
|
-
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
301
|
-
try {
|
|
302
|
-
const microfrontendsJsonContent = (0, import_node_fs2.readFileSync)(
|
|
303
|
-
microfrontendsJsonPath,
|
|
304
|
-
"utf-8"
|
|
305
|
-
);
|
|
306
|
-
const microfrontendsJson = (0, import_jsonc_parser.parse)(microfrontendsJsonContent);
|
|
307
|
-
if (microfrontendsJson.applications[applicationName]) {
|
|
308
|
-
logger.debug(
|
|
309
|
-
"[MFE Config] Found application in config:",
|
|
310
|
-
microfrontendsJsonPath
|
|
311
|
-
);
|
|
312
|
-
matchingPaths.push(microfrontendsJsonPath);
|
|
313
|
-
} else {
|
|
314
|
-
for (const [_, app] of Object.entries(
|
|
315
|
-
microfrontendsJson.applications
|
|
316
|
-
)) {
|
|
317
|
-
if (app.packageName === applicationName) {
|
|
318
|
-
logger.debug(
|
|
319
|
-
"[MFE Config] Found application via packageName in config:",
|
|
320
|
-
microfrontendsJsonPath
|
|
321
|
-
);
|
|
322
|
-
matchingPaths.push(microfrontendsJsonPath);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
} catch (error2) {
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
logger.debug(
|
|
330
|
-
"[MFE Config] Total matching config files:",
|
|
331
|
-
matchingPaths.length
|
|
332
|
-
);
|
|
333
|
-
if (matchingPaths.length > 1) {
|
|
334
|
-
throw new MicrofrontendError(
|
|
335
|
-
`Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
|
|
336
|
-
${matchingPaths.join("\n \u2022 ")}`,
|
|
337
|
-
{ type: "config", subtype: "inference_failed" }
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
if (matchingPaths.length === 0) {
|
|
341
|
-
let additionalErrorMessage = "";
|
|
342
|
-
if (microfrontendsJsonPaths.length > 0) {
|
|
343
|
-
if (!applicationContext.projectName) {
|
|
344
|
-
additionalErrorMessage = `
|
|
345
|
-
|
|
346
|
-
If the name in package.json (${applicationContext.packageJsonName}) differs from your Vercel Project name, set the \`packageName\` field for the application in \`microfrontends.json\` to ensure that the configuration can be found locally.`;
|
|
347
|
-
} else {
|
|
348
|
-
additionalErrorMessage = `
|
|
349
|
-
|
|
350
|
-
Names of applications in \`microfrontends.json\` must match the Vercel Project name (${applicationContext.projectName}).`;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
throw new MicrofrontendError(
|
|
354
|
-
`Could not find a \`microfrontends.json\` file in the repository that contains the "${applicationName}" application.${additionalErrorMessage}
|
|
355
|
-
|
|
356
|
-
If your Vercel Microfrontends configuration is not in this repository, you can use the Vercel CLI to pull the Vercel Microfrontends configuration using the "vercel microfrontends pull" command, or you can specify the path manually using the VC_MICROFRONTENDS_CONFIG environment variable.
|
|
357
160
|
|
|
358
|
-
|
|
161
|
+
// src/config/overrides/constants.ts
|
|
162
|
+
var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
|
|
163
|
+
var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
359
164
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
const [packageJsonPath] = matchingPaths;
|
|
365
|
-
return (0, import_node_path2.dirname)(packageJsonPath);
|
|
366
|
-
} catch (error2) {
|
|
367
|
-
if (error2 instanceof MicrofrontendError) {
|
|
368
|
-
throw error2;
|
|
369
|
-
}
|
|
370
|
-
return null;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
function inferMicrofrontendsLocation(opts) {
|
|
374
|
-
const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ""}`;
|
|
375
|
-
if (configCache[cacheKey]) {
|
|
376
|
-
return configCache[cacheKey];
|
|
377
|
-
}
|
|
378
|
-
const result = findPackageWithMicrofrontendsConfig(opts);
|
|
379
|
-
if (!result) {
|
|
380
|
-
throw new MicrofrontendError(
|
|
381
|
-
`Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationContext.name}" starting in directory "${opts.repositoryRoot}".`,
|
|
382
|
-
{ type: "config", subtype: "inference_failed" }
|
|
383
|
-
);
|
|
384
|
-
}
|
|
385
|
-
configCache[cacheKey] = result;
|
|
386
|
-
return result;
|
|
165
|
+
// src/config/overrides/is-override-cookie.ts
|
|
166
|
+
function isOverrideCookie(cookie) {
|
|
167
|
+
return Boolean(cookie.name?.startsWith(OVERRIDES_COOKIE_PREFIX));
|
|
387
168
|
}
|
|
388
169
|
|
|
389
|
-
// src/config/
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
return true;
|
|
398
|
-
}
|
|
399
|
-
if (import_node_fs3.default.existsSync(import_node_path3.default.join(repositoryRoot, "vlt-workspaces.json"))) {
|
|
400
|
-
return true;
|
|
401
|
-
}
|
|
402
|
-
if (process.env.NX_WORKSPACE_ROOT === import_node_path3.default.resolve(repositoryRoot)) {
|
|
403
|
-
return true;
|
|
404
|
-
}
|
|
405
|
-
const packageJsonPath = import_node_path3.default.join(repositoryRoot, "package.json");
|
|
406
|
-
if (!import_node_fs3.default.existsSync(packageJsonPath)) {
|
|
407
|
-
return false;
|
|
408
|
-
}
|
|
409
|
-
const packageJson = JSON.parse(
|
|
410
|
-
import_node_fs3.default.readFileSync(packageJsonPath, "utf-8")
|
|
411
|
-
);
|
|
412
|
-
return packageJson.workspaces !== void 0;
|
|
413
|
-
} catch (error2) {
|
|
414
|
-
logger.error("Error determining if repository is a monorepo", error2);
|
|
415
|
-
return false;
|
|
416
|
-
}
|
|
170
|
+
// src/config/overrides/get-override-from-cookie.ts
|
|
171
|
+
function getOverrideFromCookie(cookie) {
|
|
172
|
+
if (!isOverrideCookie(cookie) || !cookie.value)
|
|
173
|
+
return;
|
|
174
|
+
return {
|
|
175
|
+
application: cookie.name.replace(OVERRIDES_ENV_COOKIE_PREFIX, ""),
|
|
176
|
+
host: cookie.value
|
|
177
|
+
};
|
|
417
178
|
}
|
|
418
179
|
|
|
419
|
-
// src/config/
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
throw new Error(
|
|
433
|
-
`The root of the package that contains the \`package.json\` file for the \`${startDir}\` directory could not be found.`
|
|
434
|
-
);
|
|
180
|
+
// src/config/overrides/parse-overrides.ts
|
|
181
|
+
function parseOverrides(cookies) {
|
|
182
|
+
const overridesConfig = { applications: {} };
|
|
183
|
+
cookies.forEach((cookie) => {
|
|
184
|
+
const override = getOverrideFromCookie(cookie);
|
|
185
|
+
if (!override)
|
|
186
|
+
return;
|
|
187
|
+
overridesConfig.applications[override.application] = {
|
|
188
|
+
environment: { host: override.host }
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
return overridesConfig;
|
|
435
192
|
}
|
|
436
193
|
|
|
437
|
-
// src/config/
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
function findConfig({
|
|
441
|
-
dir,
|
|
442
|
-
customConfigFilename
|
|
443
|
-
}) {
|
|
444
|
-
for (const filename of getPossibleConfigurationFilenames({
|
|
445
|
-
customConfigFilename
|
|
446
|
-
})) {
|
|
447
|
-
const maybeConfig = (0, import_node_path5.join)(dir, filename);
|
|
448
|
-
if (import_node_fs5.default.existsSync(maybeConfig)) {
|
|
449
|
-
return maybeConfig;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
return null;
|
|
194
|
+
// src/config/schema/utils/is-default-app.ts
|
|
195
|
+
function isDefaultApp(a) {
|
|
196
|
+
return !("routing" in a);
|
|
453
197
|
}
|
|
454
198
|
|
|
455
|
-
// src/config/microfrontends-config/isomorphic/index.ts
|
|
456
|
-
var import_jsonc_parser2 = require("jsonc-parser");
|
|
457
|
-
|
|
458
199
|
// src/config/microfrontends-config/client/index.ts
|
|
459
200
|
var import_path_to_regexp = require("path-to-regexp");
|
|
460
201
|
var regexpCache = /* @__PURE__ */ new Map();
|
|
@@ -553,6 +294,183 @@ var MicrofrontendConfigClient = class {
|
|
|
553
294
|
}
|
|
554
295
|
};
|
|
555
296
|
|
|
297
|
+
// src/config/microfrontends-config/utils/get-config-from-env.ts
|
|
298
|
+
function getConfigStringFromEnv() {
|
|
299
|
+
const config = process.env.MFE_CONFIG;
|
|
300
|
+
if (!config) {
|
|
301
|
+
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
302
|
+
type: "config",
|
|
303
|
+
subtype: "not_found_in_env"
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
return config;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// src/config/microfrontends-config/isomorphic/constants.ts
|
|
310
|
+
var DEFAULT_LOCAL_PROXY_PORT = 3024;
|
|
311
|
+
var MFE_APP_PORT_ENV = "MFE_APP_PORT";
|
|
312
|
+
var MFE_LOCAL_PROXY_PORT_ENV = "MFE_LOCAL_PROXY_PORT";
|
|
313
|
+
|
|
314
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-port.ts
|
|
315
|
+
function generatePortFromName({
|
|
316
|
+
name,
|
|
317
|
+
minPort = 3e3,
|
|
318
|
+
maxPort = 8e3
|
|
319
|
+
}) {
|
|
320
|
+
if (!name) {
|
|
321
|
+
throw new Error("Name is required to generate a port");
|
|
322
|
+
}
|
|
323
|
+
let hash = 0;
|
|
324
|
+
for (let i = 0; i < name.length; i++) {
|
|
325
|
+
hash = (hash << 5) - hash + name.charCodeAt(i);
|
|
326
|
+
hash |= 0;
|
|
327
|
+
}
|
|
328
|
+
hash = Math.abs(hash);
|
|
329
|
+
const range = maxPort - minPort;
|
|
330
|
+
const port = minPort + hash % range;
|
|
331
|
+
return port;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// src/config/microfrontends-config/isomorphic/host.ts
|
|
335
|
+
var Host = class {
|
|
336
|
+
constructor(hostConfig, options) {
|
|
337
|
+
if (typeof hostConfig === "string") {
|
|
338
|
+
({
|
|
339
|
+
protocol: this.protocol,
|
|
340
|
+
host: this.host,
|
|
341
|
+
port: this.port
|
|
342
|
+
} = Host.parseUrl(hostConfig));
|
|
343
|
+
} else {
|
|
344
|
+
const { protocol = "https", host, port } = hostConfig;
|
|
345
|
+
this.protocol = protocol;
|
|
346
|
+
this.host = host;
|
|
347
|
+
this.port = port;
|
|
348
|
+
}
|
|
349
|
+
this.local = options?.isLocal;
|
|
350
|
+
}
|
|
351
|
+
static parseUrl(url, defaultProtocol = "https") {
|
|
352
|
+
let hostToParse = url;
|
|
353
|
+
if (!/^https?:\/\//.exec(hostToParse)) {
|
|
354
|
+
hostToParse = `${defaultProtocol}://${hostToParse}`;
|
|
355
|
+
}
|
|
356
|
+
const parsed = new URL(hostToParse);
|
|
357
|
+
if (!parsed.hostname) {
|
|
358
|
+
throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
|
|
359
|
+
}
|
|
360
|
+
if (parsed.hash) {
|
|
361
|
+
throw new Error(
|
|
362
|
+
Host.getMicrofrontendsError(url, "cannot have a fragment")
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
if (parsed.username || parsed.password) {
|
|
366
|
+
throw new Error(
|
|
367
|
+
Host.getMicrofrontendsError(
|
|
368
|
+
url,
|
|
369
|
+
"cannot have authentication credentials (username and/or password)"
|
|
370
|
+
)
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
if (parsed.pathname !== "/") {
|
|
374
|
+
throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
|
|
375
|
+
}
|
|
376
|
+
if (parsed.search) {
|
|
377
|
+
throw new Error(
|
|
378
|
+
Host.getMicrofrontendsError(url, "cannot have query parameters")
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
const protocol = parsed.protocol.slice(0, -1);
|
|
382
|
+
return {
|
|
383
|
+
protocol,
|
|
384
|
+
host: parsed.hostname,
|
|
385
|
+
port: parsed.port ? Number.parseInt(parsed.port, 10) : void 0
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
static getMicrofrontendsError(url, message) {
|
|
389
|
+
return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
|
|
390
|
+
}
|
|
391
|
+
isLocal() {
|
|
392
|
+
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
393
|
+
}
|
|
394
|
+
toString() {
|
|
395
|
+
const url = this.toUrl();
|
|
396
|
+
return url.toString().replace(/\/$/, "");
|
|
397
|
+
}
|
|
398
|
+
toUrl() {
|
|
399
|
+
const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
|
|
400
|
+
return new URL(url);
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
var LocalHost = class extends Host {
|
|
404
|
+
constructor({
|
|
405
|
+
appName,
|
|
406
|
+
local
|
|
407
|
+
}) {
|
|
408
|
+
const portOverride = process.env[MFE_APP_PORT_ENV];
|
|
409
|
+
if (portOverride) {
|
|
410
|
+
const overridePort = Number.parseInt(portOverride, 10);
|
|
411
|
+
if (!Number.isNaN(overridePort) && overridePort > 0 && overridePort < 65536) {
|
|
412
|
+
super({
|
|
413
|
+
protocol: "http",
|
|
414
|
+
host: "localhost",
|
|
415
|
+
port: overridePort
|
|
416
|
+
});
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
let protocol;
|
|
421
|
+
let host;
|
|
422
|
+
let port;
|
|
423
|
+
if (typeof local === "number") {
|
|
424
|
+
port = local;
|
|
425
|
+
} else if (typeof local === "string") {
|
|
426
|
+
if (/^\d+$/.test(local)) {
|
|
427
|
+
port = Number.parseInt(local, 10);
|
|
428
|
+
} else {
|
|
429
|
+
const parsed = Host.parseUrl(local, "http");
|
|
430
|
+
protocol = parsed.protocol;
|
|
431
|
+
host = parsed.host;
|
|
432
|
+
port = parsed.port;
|
|
433
|
+
}
|
|
434
|
+
} else if (local) {
|
|
435
|
+
protocol = local.protocol;
|
|
436
|
+
host = local.host;
|
|
437
|
+
port = local.port;
|
|
438
|
+
}
|
|
439
|
+
super({
|
|
440
|
+
protocol: protocol ?? "http",
|
|
441
|
+
host: host ?? "localhost",
|
|
442
|
+
port: port ?? generatePortFromName({ name: appName })
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
// src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts
|
|
448
|
+
var import_md5 = __toESM(require("md5"), 1);
|
|
449
|
+
function hashApplicationName(name) {
|
|
450
|
+
if (!name) {
|
|
451
|
+
throw new Error("Application name is required to generate hash");
|
|
452
|
+
}
|
|
453
|
+
return (0, import_md5.default)(name).substring(0, 6).padStart(6, "0");
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
|
|
457
|
+
var PREFIX = "vc-ap";
|
|
458
|
+
function generateAssetPrefixFromName({
|
|
459
|
+
name
|
|
460
|
+
}) {
|
|
461
|
+
if (!name) {
|
|
462
|
+
throw new Error("Name is required to generate an asset prefix");
|
|
463
|
+
}
|
|
464
|
+
return `${PREFIX}-${hashApplicationName(name)}`;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts
|
|
468
|
+
function generateAutomationBypassEnvVarName({
|
|
469
|
+
name
|
|
470
|
+
}) {
|
|
471
|
+
return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
472
|
+
}
|
|
473
|
+
|
|
556
474
|
// src/config/microfrontends-config/isomorphic/validation.ts
|
|
557
475
|
var import_path_to_regexp2 = require("path-to-regexp");
|
|
558
476
|
var LIST_FORMATTER = new Intl.ListFormat("en", {
|
|
@@ -734,154 +652,6 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
|
|
|
734
652
|
}
|
|
735
653
|
};
|
|
736
654
|
|
|
737
|
-
// src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts
|
|
738
|
-
var import_md5 = __toESM(require("md5"), 1);
|
|
739
|
-
function hashApplicationName(name) {
|
|
740
|
-
if (!name) {
|
|
741
|
-
throw new Error("Application name is required to generate hash");
|
|
742
|
-
}
|
|
743
|
-
return (0, import_md5.default)(name).substring(0, 6).padStart(6, "0");
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
// src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
|
|
747
|
-
var PREFIX = "vc-ap";
|
|
748
|
-
function generateAssetPrefixFromName({
|
|
749
|
-
name
|
|
750
|
-
}) {
|
|
751
|
-
if (!name) {
|
|
752
|
-
throw new Error("Name is required to generate an asset prefix");
|
|
753
|
-
}
|
|
754
|
-
return `${PREFIX}-${hashApplicationName(name)}`;
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// src/config/microfrontends-config/isomorphic/utils/generate-port.ts
|
|
758
|
-
function generatePortFromName({
|
|
759
|
-
name,
|
|
760
|
-
minPort = 3e3,
|
|
761
|
-
maxPort = 8e3
|
|
762
|
-
}) {
|
|
763
|
-
if (!name) {
|
|
764
|
-
throw new Error("Name is required to generate a port");
|
|
765
|
-
}
|
|
766
|
-
let hash = 0;
|
|
767
|
-
for (let i = 0; i < name.length; i++) {
|
|
768
|
-
hash = (hash << 5) - hash + name.charCodeAt(i);
|
|
769
|
-
hash |= 0;
|
|
770
|
-
}
|
|
771
|
-
hash = Math.abs(hash);
|
|
772
|
-
const range = maxPort - minPort;
|
|
773
|
-
const port = minPort + hash % range;
|
|
774
|
-
return port;
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
// src/config/microfrontends-config/isomorphic/host.ts
|
|
778
|
-
var Host = class {
|
|
779
|
-
constructor(hostConfig, options) {
|
|
780
|
-
if (typeof hostConfig === "string") {
|
|
781
|
-
({
|
|
782
|
-
protocol: this.protocol,
|
|
783
|
-
host: this.host,
|
|
784
|
-
port: this.port
|
|
785
|
-
} = Host.parseUrl(hostConfig));
|
|
786
|
-
} else {
|
|
787
|
-
const { protocol = "https", host, port } = hostConfig;
|
|
788
|
-
this.protocol = protocol;
|
|
789
|
-
this.host = host;
|
|
790
|
-
this.port = port;
|
|
791
|
-
}
|
|
792
|
-
this.local = options?.isLocal;
|
|
793
|
-
}
|
|
794
|
-
static parseUrl(url, defaultProtocol = "https") {
|
|
795
|
-
let hostToParse = url;
|
|
796
|
-
if (!/^https?:\/\//.exec(hostToParse)) {
|
|
797
|
-
hostToParse = `${defaultProtocol}://${hostToParse}`;
|
|
798
|
-
}
|
|
799
|
-
const parsed = new URL(hostToParse);
|
|
800
|
-
if (!parsed.hostname) {
|
|
801
|
-
throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
|
|
802
|
-
}
|
|
803
|
-
if (parsed.hash) {
|
|
804
|
-
throw new Error(
|
|
805
|
-
Host.getMicrofrontendsError(url, "cannot have a fragment")
|
|
806
|
-
);
|
|
807
|
-
}
|
|
808
|
-
if (parsed.username || parsed.password) {
|
|
809
|
-
throw new Error(
|
|
810
|
-
Host.getMicrofrontendsError(
|
|
811
|
-
url,
|
|
812
|
-
"cannot have authentication credentials (username and/or password)"
|
|
813
|
-
)
|
|
814
|
-
);
|
|
815
|
-
}
|
|
816
|
-
if (parsed.pathname !== "/") {
|
|
817
|
-
throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
|
|
818
|
-
}
|
|
819
|
-
if (parsed.search) {
|
|
820
|
-
throw new Error(
|
|
821
|
-
Host.getMicrofrontendsError(url, "cannot have query parameters")
|
|
822
|
-
);
|
|
823
|
-
}
|
|
824
|
-
const protocol = parsed.protocol.slice(0, -1);
|
|
825
|
-
return {
|
|
826
|
-
protocol,
|
|
827
|
-
host: parsed.hostname,
|
|
828
|
-
port: parsed.port ? Number.parseInt(parsed.port) : void 0
|
|
829
|
-
};
|
|
830
|
-
}
|
|
831
|
-
static getMicrofrontendsError(url, message) {
|
|
832
|
-
return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
|
|
833
|
-
}
|
|
834
|
-
isLocal() {
|
|
835
|
-
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
836
|
-
}
|
|
837
|
-
toString() {
|
|
838
|
-
const url = this.toUrl();
|
|
839
|
-
return url.toString().replace(/\/$/, "");
|
|
840
|
-
}
|
|
841
|
-
toUrl() {
|
|
842
|
-
const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
|
|
843
|
-
return new URL(url);
|
|
844
|
-
}
|
|
845
|
-
};
|
|
846
|
-
var LocalHost = class extends Host {
|
|
847
|
-
constructor({
|
|
848
|
-
appName,
|
|
849
|
-
local
|
|
850
|
-
}) {
|
|
851
|
-
let protocol;
|
|
852
|
-
let host;
|
|
853
|
-
let port;
|
|
854
|
-
if (typeof local === "number") {
|
|
855
|
-
port = local;
|
|
856
|
-
} else if (typeof local === "string") {
|
|
857
|
-
if (/^\d+$/.test(local)) {
|
|
858
|
-
port = Number.parseInt(local);
|
|
859
|
-
} else {
|
|
860
|
-
const parsed = Host.parseUrl(local, "http");
|
|
861
|
-
protocol = parsed.protocol;
|
|
862
|
-
host = parsed.host;
|
|
863
|
-
port = parsed.port;
|
|
864
|
-
}
|
|
865
|
-
} else if (local) {
|
|
866
|
-
protocol = local.protocol;
|
|
867
|
-
host = local.host;
|
|
868
|
-
port = local.port;
|
|
869
|
-
}
|
|
870
|
-
super({
|
|
871
|
-
protocol: protocol ?? "http",
|
|
872
|
-
host: host ?? "localhost",
|
|
873
|
-
port: port ?? generatePortFromName({ name: appName })
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
};
|
|
877
|
-
|
|
878
|
-
// src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts
|
|
879
|
-
function generateAutomationBypassEnvVarName({
|
|
880
|
-
name
|
|
881
|
-
}) {
|
|
882
|
-
return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
655
|
// src/config/microfrontends-config/isomorphic/application.ts
|
|
886
656
|
var Application = class {
|
|
887
657
|
constructor(name, {
|
|
@@ -962,9 +732,6 @@ var ChildApplication = class extends Application {
|
|
|
962
732
|
}
|
|
963
733
|
};
|
|
964
734
|
|
|
965
|
-
// src/config/microfrontends-config/isomorphic/constants.ts
|
|
966
|
-
var DEFAULT_LOCAL_PROXY_PORT = 3024;
|
|
967
|
-
|
|
968
735
|
// src/config/microfrontends-config/isomorphic/index.ts
|
|
969
736
|
var MicrofrontendConfigIsomorphic = class {
|
|
970
737
|
constructor({
|
|
@@ -1008,7 +775,7 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
1008
775
|
};
|
|
1009
776
|
}
|
|
1010
777
|
static validate(config) {
|
|
1011
|
-
const c = typeof config === "string" ? (0,
|
|
778
|
+
const c = typeof config === "string" ? (0, import_jsonc_parser.parse)(config) : config;
|
|
1012
779
|
validateConfigPaths(c.applications);
|
|
1013
780
|
validateConfigDefaultApplication(c.applications);
|
|
1014
781
|
return c;
|
|
@@ -1017,7 +784,7 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
1017
784
|
cookies
|
|
1018
785
|
}) {
|
|
1019
786
|
return new MicrofrontendConfigIsomorphic({
|
|
1020
|
-
config: (0,
|
|
787
|
+
config: (0, import_jsonc_parser.parse)(getConfigStringFromEnv()),
|
|
1021
788
|
overrides: parseOverrides(cookies ?? [])
|
|
1022
789
|
});
|
|
1023
790
|
}
|
|
@@ -1082,77 +849,193 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
1082
849
|
getDefaultApplication() {
|
|
1083
850
|
return this.defaultApplication;
|
|
1084
851
|
}
|
|
1085
|
-
/**
|
|
1086
|
-
* Returns the configured port for the local proxy
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
852
|
+
/**
|
|
853
|
+
* Returns the configured port for the local proxy.
|
|
854
|
+
* Can be overridden via MFE_LOCAL_PROXY_PORT environment variable.
|
|
855
|
+
*/
|
|
856
|
+
getLocalProxyPort() {
|
|
857
|
+
const portOverride = process.env[MFE_LOCAL_PROXY_PORT_ENV];
|
|
858
|
+
if (portOverride) {
|
|
859
|
+
const port = Number.parseInt(portOverride, 10);
|
|
860
|
+
if (!Number.isNaN(port) && port > 0 && port < 65536) {
|
|
861
|
+
return port;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
return this.config.options?.localProxyPort ?? DEFAULT_LOCAL_PROXY_PORT;
|
|
865
|
+
}
|
|
866
|
+
toClientConfig(options) {
|
|
867
|
+
const applications = Object.fromEntries(
|
|
868
|
+
Object.entries(this.childApplications).map(([name, application]) => [
|
|
869
|
+
hashApplicationName(name),
|
|
870
|
+
{
|
|
871
|
+
default: false,
|
|
872
|
+
routing: application.routing
|
|
873
|
+
}
|
|
874
|
+
])
|
|
875
|
+
);
|
|
876
|
+
applications[hashApplicationName(this.defaultApplication.name)] = {
|
|
877
|
+
default: true
|
|
878
|
+
};
|
|
879
|
+
return new MicrofrontendConfigClient(
|
|
880
|
+
{
|
|
881
|
+
applications
|
|
882
|
+
},
|
|
883
|
+
{
|
|
884
|
+
removeFlaggedPaths: options?.removeFlaggedPaths
|
|
885
|
+
}
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Serializes the class back to the Schema type.
|
|
890
|
+
*
|
|
891
|
+
* NOTE: This is used when writing the config to disk and must always match the input Schema
|
|
892
|
+
*/
|
|
893
|
+
toSchemaJson() {
|
|
894
|
+
return this.serialized.config;
|
|
895
|
+
}
|
|
896
|
+
serialize() {
|
|
897
|
+
return this.serialized;
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
// src/config/microfrontends/utils/find-config.ts
|
|
902
|
+
var import_node_fs = __toESM(require("fs"), 1);
|
|
903
|
+
var import_node_path = require("path");
|
|
904
|
+
|
|
905
|
+
// src/config/microfrontends/utils/get-config-file-name.ts
|
|
906
|
+
var DEFAULT_CONFIGURATION_FILENAMES = [
|
|
907
|
+
"microfrontends.json",
|
|
908
|
+
"microfrontends.jsonc"
|
|
909
|
+
];
|
|
910
|
+
function getPossibleConfigurationFilenames({
|
|
911
|
+
customConfigFilename
|
|
912
|
+
}) {
|
|
913
|
+
if (customConfigFilename) {
|
|
914
|
+
if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
|
|
915
|
+
throw new Error(
|
|
916
|
+
`Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}. The file name must end with '.json' or '.jsonc'. It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`
|
|
917
|
+
);
|
|
918
|
+
}
|
|
919
|
+
return Array.from(
|
|
920
|
+
/* @__PURE__ */ new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES])
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
return DEFAULT_CONFIGURATION_FILENAMES;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// src/config/microfrontends/utils/find-config.ts
|
|
927
|
+
function findConfig({
|
|
928
|
+
dir,
|
|
929
|
+
customConfigFilename
|
|
930
|
+
}) {
|
|
931
|
+
for (const filename of getPossibleConfigurationFilenames({
|
|
932
|
+
customConfigFilename
|
|
933
|
+
})) {
|
|
934
|
+
const maybeConfig = (0, import_node_path.join)(dir, filename);
|
|
935
|
+
if (import_node_fs.default.existsSync(maybeConfig)) {
|
|
936
|
+
return maybeConfig;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return null;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// src/config/microfrontends/utils/find-package-root.ts
|
|
943
|
+
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
944
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
945
|
+
var PACKAGE_JSON = "package.json";
|
|
946
|
+
function findPackageRoot(startDir) {
|
|
947
|
+
let currentDir = startDir || process.cwd();
|
|
948
|
+
while (currentDir !== import_node_path2.default.parse(currentDir).root) {
|
|
949
|
+
const pkgJsonPath = import_node_path2.default.join(currentDir, PACKAGE_JSON);
|
|
950
|
+
if (import_node_fs2.default.existsSync(pkgJsonPath)) {
|
|
951
|
+
return currentDir;
|
|
952
|
+
}
|
|
953
|
+
currentDir = import_node_path2.default.dirname(currentDir);
|
|
1090
954
|
}
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
955
|
+
throw new Error(
|
|
956
|
+
`The root of the package that contains the \`package.json\` file for the \`${startDir}\` directory could not be found.`
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// src/config/microfrontends/utils/find-repository-root.ts
|
|
961
|
+
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
962
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
963
|
+
var GIT_DIRECTORY = ".git";
|
|
964
|
+
function hasGitDirectory(dir) {
|
|
965
|
+
const gitPath = import_node_path3.default.join(dir, GIT_DIRECTORY);
|
|
966
|
+
return import_node_fs3.default.existsSync(gitPath) && import_node_fs3.default.statSync(gitPath).isDirectory();
|
|
967
|
+
}
|
|
968
|
+
function hasPnpmWorkspaces(dir) {
|
|
969
|
+
return import_node_fs3.default.existsSync(import_node_path3.default.join(dir, "pnpm-workspace.yaml"));
|
|
970
|
+
}
|
|
971
|
+
function hasPackageJson(dir) {
|
|
972
|
+
return import_node_fs3.default.existsSync(import_node_path3.default.join(dir, "package.json"));
|
|
973
|
+
}
|
|
974
|
+
function findRepositoryRoot(startDir) {
|
|
975
|
+
if (process.env.NX_WORKSPACE_ROOT) {
|
|
976
|
+
return process.env.NX_WORKSPACE_ROOT;
|
|
1112
977
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
978
|
+
let currentDir = startDir || process.cwd();
|
|
979
|
+
let lastPackageJsonDir = null;
|
|
980
|
+
while (currentDir !== import_node_path3.default.parse(currentDir).root) {
|
|
981
|
+
if (hasGitDirectory(currentDir) || hasPnpmWorkspaces(currentDir)) {
|
|
982
|
+
return currentDir;
|
|
983
|
+
}
|
|
984
|
+
if (hasPackageJson(currentDir)) {
|
|
985
|
+
lastPackageJsonDir = currentDir;
|
|
986
|
+
}
|
|
987
|
+
currentDir = import_node_path3.default.dirname(currentDir);
|
|
1120
988
|
}
|
|
1121
|
-
|
|
1122
|
-
return
|
|
989
|
+
if (lastPackageJsonDir) {
|
|
990
|
+
return lastPackageJsonDir;
|
|
1123
991
|
}
|
|
1124
|
-
|
|
992
|
+
throw new Error(
|
|
993
|
+
`Could not find the root of the repository for ${startDir}. Please ensure that the directory is part of a Git repository. If you suspect that this should work, please file an issue to the Vercel team.`
|
|
994
|
+
);
|
|
995
|
+
}
|
|
1125
996
|
|
|
1126
997
|
// src/config/microfrontends/utils/get-application-context.ts
|
|
1127
|
-
var
|
|
1128
|
-
var
|
|
998
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
999
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
1129
1000
|
function getApplicationContext(opts) {
|
|
1130
1001
|
if (opts?.appName) {
|
|
1131
|
-
logger.debug(
|
|
1002
|
+
logger.debug(
|
|
1003
|
+
"[MFE Config] Application name from appName parameter:",
|
|
1004
|
+
opts.appName
|
|
1005
|
+
);
|
|
1132
1006
|
return { name: opts.appName };
|
|
1133
1007
|
}
|
|
1134
1008
|
if (process.env.VERCEL_PROJECT_NAME) {
|
|
1135
|
-
logger.debug(
|
|
1009
|
+
logger.debug(
|
|
1010
|
+
"[MFE Config] Application name from VERCEL_PROJECT_NAME:",
|
|
1011
|
+
process.env.VERCEL_PROJECT_NAME
|
|
1012
|
+
);
|
|
1136
1013
|
return {
|
|
1137
1014
|
name: process.env.VERCEL_PROJECT_NAME,
|
|
1138
1015
|
projectName: process.env.VERCEL_PROJECT_NAME
|
|
1139
1016
|
};
|
|
1140
1017
|
}
|
|
1141
1018
|
if (process.env.NX_TASK_TARGET_PROJECT) {
|
|
1142
|
-
logger.debug(
|
|
1019
|
+
logger.debug(
|
|
1020
|
+
"[MFE Config] Application name from NX_TASK_TARGET_PROJECT:",
|
|
1021
|
+
process.env.NX_TASK_TARGET_PROJECT
|
|
1022
|
+
);
|
|
1143
1023
|
return {
|
|
1144
1024
|
name: process.env.NX_TASK_TARGET_PROJECT,
|
|
1145
1025
|
packageJsonName: process.env.NX_TASK_TARGET_PROJECT
|
|
1146
1026
|
};
|
|
1147
1027
|
}
|
|
1148
1028
|
try {
|
|
1149
|
-
const vercelProjectJsonPath =
|
|
1150
|
-
|
|
1029
|
+
const vercelProjectJsonPath = import_node_fs4.default.readFileSync(
|
|
1030
|
+
import_node_path4.default.join(opts?.packageRoot || ".", ".vercel", "project.json"),
|
|
1151
1031
|
"utf-8"
|
|
1152
1032
|
);
|
|
1153
1033
|
const projectJson = JSON.parse(vercelProjectJsonPath);
|
|
1154
1034
|
if (projectJson.projectName) {
|
|
1155
|
-
logger.debug(
|
|
1035
|
+
logger.debug(
|
|
1036
|
+
"[MFE Config] Application name from .vercel/project.json:",
|
|
1037
|
+
projectJson.projectName
|
|
1038
|
+
);
|
|
1156
1039
|
return {
|
|
1157
1040
|
name: projectJson.projectName,
|
|
1158
1041
|
projectName: projectJson.projectName
|
|
@@ -1161,8 +1044,8 @@ function getApplicationContext(opts) {
|
|
|
1161
1044
|
} catch (_) {
|
|
1162
1045
|
}
|
|
1163
1046
|
try {
|
|
1164
|
-
const packageJsonString =
|
|
1165
|
-
|
|
1047
|
+
const packageJsonString = import_node_fs4.default.readFileSync(
|
|
1048
|
+
import_node_path4.default.join(opts?.packageRoot || ".", "package.json"),
|
|
1166
1049
|
"utf-8"
|
|
1167
1050
|
);
|
|
1168
1051
|
const packageJson = JSON.parse(packageJsonString);
|
|
@@ -1176,7 +1059,10 @@ function getApplicationContext(opts) {
|
|
|
1176
1059
|
}
|
|
1177
1060
|
);
|
|
1178
1061
|
}
|
|
1179
|
-
logger.debug(
|
|
1062
|
+
logger.debug(
|
|
1063
|
+
"[MFE Config] Application name from package.json:",
|
|
1064
|
+
packageJson.name
|
|
1065
|
+
);
|
|
1180
1066
|
return { name: packageJson.name, packageJsonName: packageJson.name };
|
|
1181
1067
|
} catch (err) {
|
|
1182
1068
|
throw MicrofrontendError.handle(err, {
|
|
@@ -1185,6 +1071,209 @@ function getApplicationContext(opts) {
|
|
|
1185
1071
|
}
|
|
1186
1072
|
}
|
|
1187
1073
|
|
|
1074
|
+
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
1075
|
+
var import_node_fs5 = require("fs");
|
|
1076
|
+
var import_node_path5 = require("path");
|
|
1077
|
+
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
1078
|
+
var import_jsonc_parser2 = require("jsonc-parser");
|
|
1079
|
+
var configCache = {};
|
|
1080
|
+
function findPackageWithMicrofrontendsConfig({
|
|
1081
|
+
repositoryRoot,
|
|
1082
|
+
applicationContext,
|
|
1083
|
+
customConfigFilename
|
|
1084
|
+
}) {
|
|
1085
|
+
const applicationName = applicationContext.name;
|
|
1086
|
+
logger.debug(
|
|
1087
|
+
"[MFE Config] Searching repository for configs containing application:",
|
|
1088
|
+
applicationName
|
|
1089
|
+
);
|
|
1090
|
+
try {
|
|
1091
|
+
const microfrontendsJsonPaths = import_fast_glob.default.globSync(
|
|
1092
|
+
`**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
|
|
1093
|
+
{
|
|
1094
|
+
cwd: repositoryRoot,
|
|
1095
|
+
absolute: true,
|
|
1096
|
+
onlyFiles: true,
|
|
1097
|
+
followSymbolicLinks: false,
|
|
1098
|
+
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
1099
|
+
}
|
|
1100
|
+
);
|
|
1101
|
+
logger.debug(
|
|
1102
|
+
"[MFE Config] Found",
|
|
1103
|
+
microfrontendsJsonPaths.length,
|
|
1104
|
+
"config file(s) in repository"
|
|
1105
|
+
);
|
|
1106
|
+
const matchingPaths = [];
|
|
1107
|
+
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
1108
|
+
if (doesApplicationExistInConfig(microfrontendsJsonPath, applicationName)) {
|
|
1109
|
+
matchingPaths.push(microfrontendsJsonPath);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
logger.debug(
|
|
1113
|
+
"[MFE Config] Total matching config files:",
|
|
1114
|
+
matchingPaths.length
|
|
1115
|
+
);
|
|
1116
|
+
if (matchingPaths.length > 1) {
|
|
1117
|
+
throw new MicrofrontendError(
|
|
1118
|
+
`Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
|
|
1119
|
+
${matchingPaths.join("\n \u2022 ")}`,
|
|
1120
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1121
|
+
);
|
|
1122
|
+
}
|
|
1123
|
+
if (matchingPaths.length === 0) {
|
|
1124
|
+
if (repositoryRoot && doesMisplacedConfigExist(
|
|
1125
|
+
repositoryRoot,
|
|
1126
|
+
applicationName,
|
|
1127
|
+
customConfigFilename
|
|
1128
|
+
)) {
|
|
1129
|
+
logger.debug(
|
|
1130
|
+
"[MFE Config] Found misplaced config in wrong .vercel directory in repository"
|
|
1131
|
+
);
|
|
1132
|
+
const misplacedConfigPath = (0, import_node_path5.join)(
|
|
1133
|
+
repositoryRoot,
|
|
1134
|
+
".vercel",
|
|
1135
|
+
customConfigFilename || "microfrontends.json"
|
|
1136
|
+
);
|
|
1137
|
+
throw new MicrofrontendError(
|
|
1138
|
+
`Unable to automatically infer the location of the \`microfrontends.json\` file.
|
|
1139
|
+
|
|
1140
|
+
A microfrontends config was found in the \`.vercel\` directory at the repository root: ${misplacedConfigPath}
|
|
1141
|
+
However, in a monorepo, the config file should be placed in the \`.vercel\` directory in your application directory instead.
|
|
1142
|
+
|
|
1143
|
+
To fix this:
|
|
1144
|
+
1. If using \`vercel link\`, run it with \`vercel link --repo\` to handle monorepos, or run \`vercel microfrontends pull --cwd=<application-directory>\` to make sure it pulls the \`microfrontends.json\` file to the correct location
|
|
1145
|
+
2. If manually defined, move the config file to the \`.vercel\` directory in your application
|
|
1146
|
+
3. Alternatively, set the VC_MICROFRONTENDS_CONFIG environment variable to the correct path
|
|
1147
|
+
|
|
1148
|
+
For more information, see: https://vercel.com/docs/cli/project-linking`,
|
|
1149
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
let additionalErrorMessage = "";
|
|
1153
|
+
if (microfrontendsJsonPaths.length > 0) {
|
|
1154
|
+
if (!applicationContext.projectName) {
|
|
1155
|
+
additionalErrorMessage = `
|
|
1156
|
+
|
|
1157
|
+
If the name in package.json (${applicationContext.packageJsonName}) differs from your Vercel Project name, set the \`packageName\` field for the application in \`microfrontends.json\` to ensure that the configuration can be found locally.`;
|
|
1158
|
+
} else {
|
|
1159
|
+
additionalErrorMessage = `
|
|
1160
|
+
|
|
1161
|
+
Names of applications in \`microfrontends.json\` must match the Vercel Project name (${applicationContext.projectName}).`;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
throw new MicrofrontendError(
|
|
1165
|
+
`Could not find a \`microfrontends.json\` file in the repository that contains the "${applicationName}" application.${additionalErrorMessage}
|
|
1166
|
+
|
|
1167
|
+
If your Vercel Microfrontends configuration is not in this repository, you can use the Vercel CLI to pull the Vercel Microfrontends configuration using the "vercel microfrontends pull" command, or you can specify the path manually using the VC_MICROFRONTENDS_CONFIG environment variable.
|
|
1168
|
+
|
|
1169
|
+
If your Vercel Microfrontends configuration has a custom name, ensure the VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable is set, you can pull the vercel project environment variables using the "vercel env pull" command.
|
|
1170
|
+
|
|
1171
|
+
If you suspect this is thrown in error, please reach out to the Vercel team.`,
|
|
1172
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1173
|
+
);
|
|
1174
|
+
}
|
|
1175
|
+
const [packageJsonPath] = matchingPaths;
|
|
1176
|
+
return (0, import_node_path5.dirname)(packageJsonPath);
|
|
1177
|
+
} catch (error2) {
|
|
1178
|
+
if (error2 instanceof MicrofrontendError) {
|
|
1179
|
+
throw error2;
|
|
1180
|
+
}
|
|
1181
|
+
return null;
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
function inferMicrofrontendsLocation(opts) {
|
|
1185
|
+
const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ""}`;
|
|
1186
|
+
if (configCache[cacheKey]) {
|
|
1187
|
+
return configCache[cacheKey];
|
|
1188
|
+
}
|
|
1189
|
+
const result = findPackageWithMicrofrontendsConfig(opts);
|
|
1190
|
+
if (!result) {
|
|
1191
|
+
throw new MicrofrontendError(
|
|
1192
|
+
`Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationContext.name}" starting in directory "${opts.repositoryRoot}".`,
|
|
1193
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1194
|
+
);
|
|
1195
|
+
}
|
|
1196
|
+
configCache[cacheKey] = result;
|
|
1197
|
+
return result;
|
|
1198
|
+
}
|
|
1199
|
+
function existsSync(path7) {
|
|
1200
|
+
try {
|
|
1201
|
+
(0, import_node_fs5.statSync)(path7);
|
|
1202
|
+
return true;
|
|
1203
|
+
} catch (_) {
|
|
1204
|
+
return false;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
function doesMisplacedConfigExist(repositoryRoot, applicationName, customConfigFilename) {
|
|
1208
|
+
logger.debug(
|
|
1209
|
+
"[MFE Config] Looking for misplaced config in wrong .vercel directory"
|
|
1210
|
+
);
|
|
1211
|
+
const misplacedConfigPath = (0, import_node_path5.join)(
|
|
1212
|
+
repositoryRoot,
|
|
1213
|
+
".vercel",
|
|
1214
|
+
customConfigFilename || "microfrontends.json"
|
|
1215
|
+
);
|
|
1216
|
+
return existsSync(misplacedConfigPath) && doesApplicationExistInConfig(misplacedConfigPath, applicationName);
|
|
1217
|
+
}
|
|
1218
|
+
function doesApplicationExistInConfig(microfrontendsJsonPath, applicationName) {
|
|
1219
|
+
try {
|
|
1220
|
+
const microfrontendsJsonContent = (0, import_node_fs5.readFileSync)(
|
|
1221
|
+
microfrontendsJsonPath,
|
|
1222
|
+
"utf-8"
|
|
1223
|
+
);
|
|
1224
|
+
const microfrontendsJson = (0, import_jsonc_parser2.parse)(microfrontendsJsonContent);
|
|
1225
|
+
if (microfrontendsJson.applications[applicationName]) {
|
|
1226
|
+
logger.debug(
|
|
1227
|
+
"[MFE Config] Found application in config:",
|
|
1228
|
+
microfrontendsJsonPath
|
|
1229
|
+
);
|
|
1230
|
+
return true;
|
|
1231
|
+
}
|
|
1232
|
+
for (const [_, app] of Object.entries(microfrontendsJson.applications)) {
|
|
1233
|
+
if (app.packageName === applicationName) {
|
|
1234
|
+
logger.debug(
|
|
1235
|
+
"[MFE Config] Found application via packageName in config:",
|
|
1236
|
+
microfrontendsJsonPath
|
|
1237
|
+
);
|
|
1238
|
+
return true;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
} catch (error2) {
|
|
1242
|
+
logger.debug("[MFE Config] Error checking application in config:", error2);
|
|
1243
|
+
}
|
|
1244
|
+
return false;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// src/config/microfrontends/utils/is-monorepo.ts
|
|
1248
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
1249
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
1250
|
+
function isMonorepo({
|
|
1251
|
+
repositoryRoot
|
|
1252
|
+
}) {
|
|
1253
|
+
try {
|
|
1254
|
+
if (import_node_fs6.default.existsSync(import_node_path6.default.join(repositoryRoot, "pnpm-workspace.yaml"))) {
|
|
1255
|
+
return true;
|
|
1256
|
+
}
|
|
1257
|
+
if (import_node_fs6.default.existsSync(import_node_path6.default.join(repositoryRoot, "vlt-workspaces.json"))) {
|
|
1258
|
+
return true;
|
|
1259
|
+
}
|
|
1260
|
+
if (process.env.NX_WORKSPACE_ROOT === import_node_path6.default.resolve(repositoryRoot)) {
|
|
1261
|
+
return true;
|
|
1262
|
+
}
|
|
1263
|
+
const packageJsonPath = import_node_path6.default.join(repositoryRoot, "package.json");
|
|
1264
|
+
if (!import_node_fs6.default.existsSync(packageJsonPath)) {
|
|
1265
|
+
return false;
|
|
1266
|
+
}
|
|
1267
|
+
const packageJson = JSON.parse(
|
|
1268
|
+
import_node_fs6.default.readFileSync(packageJsonPath, "utf-8")
|
|
1269
|
+
);
|
|
1270
|
+
return packageJson.workspaces !== void 0;
|
|
1271
|
+
} catch (error2) {
|
|
1272
|
+
logger.error("Error determining if repository is a monorepo", error2);
|
|
1273
|
+
return false;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1188
1277
|
// src/config/microfrontends/server/utils/get-output-file-path.ts
|
|
1189
1278
|
var import_node_path7 = __toESM(require("path"), 1);
|
|
1190
1279
|
|
|
@@ -1198,8 +1287,8 @@ function getOutputFilePath() {
|
|
|
1198
1287
|
}
|
|
1199
1288
|
|
|
1200
1289
|
// src/config/microfrontends/server/validation.ts
|
|
1201
|
-
var import_jsonc_parser3 = require("jsonc-parser");
|
|
1202
1290
|
var import_ajv = require("ajv");
|
|
1291
|
+
var import_jsonc_parser3 = require("jsonc-parser");
|
|
1203
1292
|
|
|
1204
1293
|
// schema/schema.json
|
|
1205
1294
|
var schema_default = {
|
|
@@ -1227,9 +1316,7 @@ var schema_default = {
|
|
|
1227
1316
|
description: "Optional configuration options for the microfrontend."
|
|
1228
1317
|
}
|
|
1229
1318
|
},
|
|
1230
|
-
required: [
|
|
1231
|
-
"applications"
|
|
1232
|
-
],
|
|
1319
|
+
required: ["applications"],
|
|
1233
1320
|
additionalProperties: false,
|
|
1234
1321
|
description: "The microfrontends configuration schema. See https://vercel.com/docs/microfrontends/configuration."
|
|
1235
1322
|
},
|
|
@@ -1266,19 +1353,14 @@ var schema_default = {
|
|
|
1266
1353
|
description: "Development configuration for the default application."
|
|
1267
1354
|
}
|
|
1268
1355
|
},
|
|
1269
|
-
required: [
|
|
1270
|
-
"development"
|
|
1271
|
-
],
|
|
1356
|
+
required: ["development"],
|
|
1272
1357
|
additionalProperties: false
|
|
1273
1358
|
},
|
|
1274
1359
|
DefaultDevelopment: {
|
|
1275
1360
|
type: "object",
|
|
1276
1361
|
properties: {
|
|
1277
1362
|
local: {
|
|
1278
|
-
type: [
|
|
1279
|
-
"number",
|
|
1280
|
-
"string"
|
|
1281
|
-
],
|
|
1363
|
+
type: ["number", "string"],
|
|
1282
1364
|
description: "A local port number or host that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional).\n\nExamples of valid values: 8080, my.localhost.me, my.localhost.me:8080, https://my.localhost.me, https://my.localhost.me:8080.\n\nThe default value is http://localhost:<port> where port is a stable, unique port number (based on the application name).\n\nSee https://vercel.com/docs/microfrontends/local-development."
|
|
1283
1365
|
},
|
|
1284
1366
|
task: {
|
|
@@ -1290,9 +1372,7 @@ var schema_default = {
|
|
|
1290
1372
|
description: "Fallback for local development, could point to any environment. This is required for the default app. This value is used as the fallback for child apps as well if they do not have a fallback.\n\nIf passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTPS. If omitted, the port defaults to `80` for HTTP and `443` for HTTPS.\n\nSee https://vercel.com/docs/microfrontends/local-development."
|
|
1291
1373
|
}
|
|
1292
1374
|
},
|
|
1293
|
-
required: [
|
|
1294
|
-
"fallback"
|
|
1295
|
-
],
|
|
1375
|
+
required: ["fallback"],
|
|
1296
1376
|
additionalProperties: false
|
|
1297
1377
|
},
|
|
1298
1378
|
ChildApplication: {
|
|
@@ -1315,19 +1395,14 @@ var schema_default = {
|
|
|
1315
1395
|
description: "The name of the asset prefix to use instead of the auto-generated name.\n\nThe asset prefix is used to prefix all paths to static assets, such as JS, CSS, or images that are served by a specific application. It is necessary to ensure there are no conflicts with other applications on the same domain.\n\nAn auto-generated asset prefix of the form `vc-ap-<hash>` is used when this field is not provided.\n\nWhen this field is provided, `/${assetPrefix}/:path*` must also be added to the list of paths in the `routing` field. Changing the asset prefix after a microfrontend application has already been deployed is not a forwards and backwards compatible change, and the asset prefix should be added to the `routing` field and deployed before setting the `assetPrefix` field.\n\nThe default value is the auto-generated asset prefix of the form `vc-ap-<hash>`.\n\nSee https://vercel.com/docs/microfrontends/path-routing#asset-prefix."
|
|
1316
1396
|
}
|
|
1317
1397
|
},
|
|
1318
|
-
required: [
|
|
1319
|
-
"routing"
|
|
1320
|
-
],
|
|
1398
|
+
required: ["routing"],
|
|
1321
1399
|
additionalProperties: false
|
|
1322
1400
|
},
|
|
1323
1401
|
ChildDevelopment: {
|
|
1324
1402
|
type: "object",
|
|
1325
1403
|
properties: {
|
|
1326
1404
|
local: {
|
|
1327
|
-
type: [
|
|
1328
|
-
"number",
|
|
1329
|
-
"string"
|
|
1330
|
-
],
|
|
1405
|
+
type: ["number", "string"],
|
|
1331
1406
|
description: "A local port number or host that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional).\n\nExamples of valid values: 8080, my.localhost.me, my.localhost.me:8080, https://my.localhost.me, https://my.localhost.me:8080.\n\nThe default value is http://localhost:<port> where port is a stable, unique port number (based on the application name).\n\nSee https://vercel.com/docs/microfrontends/local-development."
|
|
1332
1407
|
},
|
|
1333
1408
|
task: {
|
|
@@ -1367,9 +1442,7 @@ var schema_default = {
|
|
|
1367
1442
|
description: "A list of path expressions that are routed to this application. See https://vercel.com/docs/microfrontends/path-routing#supported-path-expressions."
|
|
1368
1443
|
}
|
|
1369
1444
|
},
|
|
1370
|
-
required: [
|
|
1371
|
-
"paths"
|
|
1372
|
-
],
|
|
1445
|
+
required: ["paths"],
|
|
1373
1446
|
additionalProperties: false,
|
|
1374
1447
|
description: "A group of paths that is routed to this application."
|
|
1375
1448
|
},
|
|
@@ -1732,8 +1805,21 @@ var MicrofrontendsServer = class {
|
|
|
1732
1805
|
};
|
|
1733
1806
|
|
|
1734
1807
|
// src/utils/mfe-port.ts
|
|
1808
|
+
var MFE_APP_PORT_ENV2 = "MFE_APP_PORT";
|
|
1735
1809
|
function mfePort(packageDir) {
|
|
1736
1810
|
const { name: appName, version } = getPackageJson(packageDir);
|
|
1811
|
+
const portOverride = process.env[MFE_APP_PORT_ENV2];
|
|
1812
|
+
if (portOverride) {
|
|
1813
|
+
const port = Number.parseInt(portOverride, 10);
|
|
1814
|
+
if (!Number.isNaN(port) && port > 0 && port < 65536) {
|
|
1815
|
+
return {
|
|
1816
|
+
name: appName,
|
|
1817
|
+
version,
|
|
1818
|
+
port,
|
|
1819
|
+
overridden: true
|
|
1820
|
+
};
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1737
1823
|
try {
|
|
1738
1824
|
const result = loadConfig({ packageDir, appName });
|
|
1739
1825
|
const { port } = result;
|
|
@@ -1765,6 +1851,7 @@ function loadConfig({
|
|
|
1765
1851
|
}
|
|
1766
1852
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1767
1853
|
0 && (module.exports = {
|
|
1854
|
+
MFE_APP_PORT_ENV,
|
|
1768
1855
|
mfePort
|
|
1769
1856
|
});
|
|
1770
1857
|
//# sourceMappingURL=mfe-port.cjs.map
|