@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
|
@@ -73,39 +73,6 @@ function displayLocalProxyInfo(port) {
|
|
|
73
73
|
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
74
74
|
var import_node_path8 = require("path");
|
|
75
75
|
|
|
76
|
-
// src/config/overrides/constants.ts
|
|
77
|
-
var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
|
|
78
|
-
var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
79
|
-
|
|
80
|
-
// src/config/overrides/is-override-cookie.ts
|
|
81
|
-
function isOverrideCookie(cookie) {
|
|
82
|
-
return Boolean(cookie.name?.startsWith(OVERRIDES_COOKIE_PREFIX));
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// src/config/overrides/get-override-from-cookie.ts
|
|
86
|
-
function getOverrideFromCookie(cookie) {
|
|
87
|
-
if (!isOverrideCookie(cookie) || !cookie.value)
|
|
88
|
-
return;
|
|
89
|
-
return {
|
|
90
|
-
application: cookie.name.replace(OVERRIDES_ENV_COOKIE_PREFIX, ""),
|
|
91
|
-
host: cookie.value
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// src/config/overrides/parse-overrides.ts
|
|
96
|
-
function parseOverrides(cookies) {
|
|
97
|
-
const overridesConfig = { applications: {} };
|
|
98
|
-
cookies.forEach((cookie) => {
|
|
99
|
-
const override = getOverrideFromCookie(cookie);
|
|
100
|
-
if (!override)
|
|
101
|
-
return;
|
|
102
|
-
overridesConfig.applications[override.application] = {
|
|
103
|
-
environment: { host: override.host }
|
|
104
|
-
};
|
|
105
|
-
});
|
|
106
|
-
return overridesConfig;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
76
|
// src/config/errors.ts
|
|
110
77
|
var MicrofrontendError = class extends Error {
|
|
111
78
|
constructor(message, opts) {
|
|
@@ -198,274 +165,47 @@ var MicrofrontendError = class extends Error {
|
|
|
198
165
|
}
|
|
199
166
|
};
|
|
200
167
|
|
|
201
|
-
// src/config/microfrontends-config/
|
|
202
|
-
function getConfigStringFromEnv() {
|
|
203
|
-
const config = process.env.MFE_CONFIG;
|
|
204
|
-
if (!config) {
|
|
205
|
-
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
206
|
-
type: "config",
|
|
207
|
-
subtype: "not_found_in_env"
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
return config;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// src/config/schema/utils/is-default-app.ts
|
|
214
|
-
function isDefaultApp(a) {
|
|
215
|
-
return !("routing" in a);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// src/config/microfrontends/utils/find-repository-root.ts
|
|
219
|
-
var import_node_fs = __toESM(require("fs"), 1);
|
|
220
|
-
var import_node_path = __toESM(require("path"), 1);
|
|
221
|
-
var GIT_DIRECTORY = ".git";
|
|
222
|
-
function hasGitDirectory(dir) {
|
|
223
|
-
const gitPath = import_node_path.default.join(dir, GIT_DIRECTORY);
|
|
224
|
-
return import_node_fs.default.existsSync(gitPath) && import_node_fs.default.statSync(gitPath).isDirectory();
|
|
225
|
-
}
|
|
226
|
-
function hasPnpmWorkspaces(dir) {
|
|
227
|
-
return import_node_fs.default.existsSync(import_node_path.default.join(dir, "pnpm-workspace.yaml"));
|
|
228
|
-
}
|
|
229
|
-
function hasPackageJson(dir) {
|
|
230
|
-
return import_node_fs.default.existsSync(import_node_path.default.join(dir, "package.json"));
|
|
231
|
-
}
|
|
232
|
-
function findRepositoryRoot(startDir) {
|
|
233
|
-
if (process.env.NX_WORKSPACE_ROOT) {
|
|
234
|
-
return process.env.NX_WORKSPACE_ROOT;
|
|
235
|
-
}
|
|
236
|
-
let currentDir = startDir || process.cwd();
|
|
237
|
-
let lastPackageJsonDir = null;
|
|
238
|
-
while (currentDir !== import_node_path.default.parse(currentDir).root) {
|
|
239
|
-
if (hasGitDirectory(currentDir) || hasPnpmWorkspaces(currentDir)) {
|
|
240
|
-
return currentDir;
|
|
241
|
-
}
|
|
242
|
-
if (hasPackageJson(currentDir)) {
|
|
243
|
-
lastPackageJsonDir = currentDir;
|
|
244
|
-
}
|
|
245
|
-
currentDir = import_node_path.default.dirname(currentDir);
|
|
246
|
-
}
|
|
247
|
-
if (lastPackageJsonDir) {
|
|
248
|
-
return lastPackageJsonDir;
|
|
249
|
-
}
|
|
250
|
-
throw new Error(
|
|
251
|
-
`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.`
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
256
|
-
var import_node_path2 = require("path");
|
|
257
|
-
var import_node_fs2 = require("fs");
|
|
168
|
+
// src/config/microfrontends-config/isomorphic/index.ts
|
|
258
169
|
var import_jsonc_parser = require("jsonc-parser");
|
|
259
|
-
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
260
|
-
|
|
261
|
-
// src/config/microfrontends/utils/get-config-file-name.ts
|
|
262
|
-
var DEFAULT_CONFIGURATION_FILENAMES = [
|
|
263
|
-
"microfrontends.json",
|
|
264
|
-
"microfrontends.jsonc"
|
|
265
|
-
];
|
|
266
|
-
function getPossibleConfigurationFilenames({
|
|
267
|
-
customConfigFilename
|
|
268
|
-
}) {
|
|
269
|
-
if (customConfigFilename) {
|
|
270
|
-
if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
|
|
271
|
-
throw new Error(
|
|
272
|
-
`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.`
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
return Array.from(
|
|
276
|
-
/* @__PURE__ */ new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES])
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
return DEFAULT_CONFIGURATION_FILENAMES;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
283
|
-
var configCache = {};
|
|
284
|
-
function findPackageWithMicrofrontendsConfig({
|
|
285
|
-
repositoryRoot,
|
|
286
|
-
applicationContext,
|
|
287
|
-
customConfigFilename
|
|
288
|
-
}) {
|
|
289
|
-
const applicationName = applicationContext.name;
|
|
290
|
-
logger.debug(
|
|
291
|
-
"[MFE Config] Searching repository for configs containing application:",
|
|
292
|
-
applicationName
|
|
293
|
-
);
|
|
294
|
-
try {
|
|
295
|
-
const microfrontendsJsonPaths = import_fast_glob.default.globSync(
|
|
296
|
-
`**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
|
|
297
|
-
{
|
|
298
|
-
cwd: repositoryRoot,
|
|
299
|
-
absolute: true,
|
|
300
|
-
onlyFiles: true,
|
|
301
|
-
followSymbolicLinks: false,
|
|
302
|
-
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
303
|
-
}
|
|
304
|
-
);
|
|
305
|
-
logger.debug(
|
|
306
|
-
"[MFE Config] Found",
|
|
307
|
-
microfrontendsJsonPaths.length,
|
|
308
|
-
"config file(s) in repository"
|
|
309
|
-
);
|
|
310
|
-
const matchingPaths = [];
|
|
311
|
-
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
312
|
-
try {
|
|
313
|
-
const microfrontendsJsonContent = (0, import_node_fs2.readFileSync)(
|
|
314
|
-
microfrontendsJsonPath,
|
|
315
|
-
"utf-8"
|
|
316
|
-
);
|
|
317
|
-
const microfrontendsJson = (0, import_jsonc_parser.parse)(microfrontendsJsonContent);
|
|
318
|
-
if (microfrontendsJson.applications[applicationName]) {
|
|
319
|
-
logger.debug(
|
|
320
|
-
"[MFE Config] Found application in config:",
|
|
321
|
-
microfrontendsJsonPath
|
|
322
|
-
);
|
|
323
|
-
matchingPaths.push(microfrontendsJsonPath);
|
|
324
|
-
} else {
|
|
325
|
-
for (const [_, app] of Object.entries(
|
|
326
|
-
microfrontendsJson.applications
|
|
327
|
-
)) {
|
|
328
|
-
if (app.packageName === applicationName) {
|
|
329
|
-
logger.debug(
|
|
330
|
-
"[MFE Config] Found application via packageName in config:",
|
|
331
|
-
microfrontendsJsonPath
|
|
332
|
-
);
|
|
333
|
-
matchingPaths.push(microfrontendsJsonPath);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
} catch (error2) {
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
logger.debug(
|
|
341
|
-
"[MFE Config] Total matching config files:",
|
|
342
|
-
matchingPaths.length
|
|
343
|
-
);
|
|
344
|
-
if (matchingPaths.length > 1) {
|
|
345
|
-
throw new MicrofrontendError(
|
|
346
|
-
`Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
|
|
347
|
-
${matchingPaths.join("\n \u2022 ")}`,
|
|
348
|
-
{ type: "config", subtype: "inference_failed" }
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
if (matchingPaths.length === 0) {
|
|
352
|
-
let additionalErrorMessage = "";
|
|
353
|
-
if (microfrontendsJsonPaths.length > 0) {
|
|
354
|
-
if (!applicationContext.projectName) {
|
|
355
|
-
additionalErrorMessage = `
|
|
356
170
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
Names of applications in \`microfrontends.json\` must match the Vercel Project name (${applicationContext.projectName}).`;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
throw new MicrofrontendError(
|
|
365
|
-
`Could not find a \`microfrontends.json\` file in the repository that contains the "${applicationName}" application.${additionalErrorMessage}
|
|
366
|
-
|
|
367
|
-
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.
|
|
368
|
-
|
|
369
|
-
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.
|
|
171
|
+
// src/config/overrides/constants.ts
|
|
172
|
+
var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
|
|
173
|
+
var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;
|
|
370
174
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
const [packageJsonPath] = matchingPaths;
|
|
376
|
-
return (0, import_node_path2.dirname)(packageJsonPath);
|
|
377
|
-
} catch (error2) {
|
|
378
|
-
if (error2 instanceof MicrofrontendError) {
|
|
379
|
-
throw error2;
|
|
380
|
-
}
|
|
381
|
-
return null;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
function inferMicrofrontendsLocation(opts) {
|
|
385
|
-
const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ""}`;
|
|
386
|
-
if (configCache[cacheKey]) {
|
|
387
|
-
return configCache[cacheKey];
|
|
388
|
-
}
|
|
389
|
-
const result = findPackageWithMicrofrontendsConfig(opts);
|
|
390
|
-
if (!result) {
|
|
391
|
-
throw new MicrofrontendError(
|
|
392
|
-
`Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationContext.name}" starting in directory "${opts.repositoryRoot}".`,
|
|
393
|
-
{ type: "config", subtype: "inference_failed" }
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
configCache[cacheKey] = result;
|
|
397
|
-
return result;
|
|
175
|
+
// src/config/overrides/is-override-cookie.ts
|
|
176
|
+
function isOverrideCookie(cookie) {
|
|
177
|
+
return Boolean(cookie.name?.startsWith(OVERRIDES_COOKIE_PREFIX));
|
|
398
178
|
}
|
|
399
179
|
|
|
400
|
-
// src/config/
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
return true;
|
|
409
|
-
}
|
|
410
|
-
if (import_node_fs3.default.existsSync(import_node_path3.default.join(repositoryRoot, "vlt-workspaces.json"))) {
|
|
411
|
-
return true;
|
|
412
|
-
}
|
|
413
|
-
if (process.env.NX_WORKSPACE_ROOT === import_node_path3.default.resolve(repositoryRoot)) {
|
|
414
|
-
return true;
|
|
415
|
-
}
|
|
416
|
-
const packageJsonPath = import_node_path3.default.join(repositoryRoot, "package.json");
|
|
417
|
-
if (!import_node_fs3.default.existsSync(packageJsonPath)) {
|
|
418
|
-
return false;
|
|
419
|
-
}
|
|
420
|
-
const packageJson = JSON.parse(
|
|
421
|
-
import_node_fs3.default.readFileSync(packageJsonPath, "utf-8")
|
|
422
|
-
);
|
|
423
|
-
return packageJson.workspaces !== void 0;
|
|
424
|
-
} catch (error2) {
|
|
425
|
-
logger.error("Error determining if repository is a monorepo", error2);
|
|
426
|
-
return false;
|
|
427
|
-
}
|
|
180
|
+
// src/config/overrides/get-override-from-cookie.ts
|
|
181
|
+
function getOverrideFromCookie(cookie) {
|
|
182
|
+
if (!isOverrideCookie(cookie) || !cookie.value)
|
|
183
|
+
return;
|
|
184
|
+
return {
|
|
185
|
+
application: cookie.name.replace(OVERRIDES_ENV_COOKIE_PREFIX, ""),
|
|
186
|
+
host: cookie.value
|
|
187
|
+
};
|
|
428
188
|
}
|
|
429
189
|
|
|
430
|
-
// src/config/
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
throw new Error(
|
|
444
|
-
`The root of the package that contains the \`package.json\` file for the \`${startDir}\` directory could not be found.`
|
|
445
|
-
);
|
|
190
|
+
// src/config/overrides/parse-overrides.ts
|
|
191
|
+
function parseOverrides(cookies) {
|
|
192
|
+
const overridesConfig = { applications: {} };
|
|
193
|
+
cookies.forEach((cookie) => {
|
|
194
|
+
const override = getOverrideFromCookie(cookie);
|
|
195
|
+
if (!override)
|
|
196
|
+
return;
|
|
197
|
+
overridesConfig.applications[override.application] = {
|
|
198
|
+
environment: { host: override.host }
|
|
199
|
+
};
|
|
200
|
+
});
|
|
201
|
+
return overridesConfig;
|
|
446
202
|
}
|
|
447
203
|
|
|
448
|
-
// src/config/
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
function findConfig({
|
|
452
|
-
dir,
|
|
453
|
-
customConfigFilename
|
|
454
|
-
}) {
|
|
455
|
-
for (const filename of getPossibleConfigurationFilenames({
|
|
456
|
-
customConfigFilename
|
|
457
|
-
})) {
|
|
458
|
-
const maybeConfig = (0, import_node_path5.join)(dir, filename);
|
|
459
|
-
if (import_node_fs5.default.existsSync(maybeConfig)) {
|
|
460
|
-
return maybeConfig;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
return null;
|
|
204
|
+
// src/config/schema/utils/is-default-app.ts
|
|
205
|
+
function isDefaultApp(a) {
|
|
206
|
+
return !("routing" in a);
|
|
464
207
|
}
|
|
465
208
|
|
|
466
|
-
// src/config/microfrontends-config/isomorphic/index.ts
|
|
467
|
-
var import_jsonc_parser2 = require("jsonc-parser");
|
|
468
|
-
|
|
469
209
|
// src/config/microfrontends-config/client/index.ts
|
|
470
210
|
var import_path_to_regexp = require("path-to-regexp");
|
|
471
211
|
var regexpCache = /* @__PURE__ */ new Map();
|
|
@@ -524,46 +264,223 @@ var MicrofrontendConfigClient = class {
|
|
|
524
264
|
"Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`? Is the local proxy running and this application is being accessed via the proxy port? See https://vercel.com/docs/microfrontends/local-development#setting-up-microfrontends-proxy"
|
|
525
265
|
);
|
|
526
266
|
}
|
|
527
|
-
return new MicrofrontendConfigClient(JSON.parse(config));
|
|
267
|
+
return new MicrofrontendConfigClient(JSON.parse(config));
|
|
268
|
+
}
|
|
269
|
+
isEqual(other) {
|
|
270
|
+
return this === other || JSON.stringify(this.applications) === JSON.stringify(other.applications);
|
|
271
|
+
}
|
|
272
|
+
getApplicationNameForPath(path6) {
|
|
273
|
+
if (!path6.startsWith("/")) {
|
|
274
|
+
throw new Error(`Path must start with a /`);
|
|
275
|
+
}
|
|
276
|
+
if (this.pathCache[path6]) {
|
|
277
|
+
return this.pathCache[path6];
|
|
278
|
+
}
|
|
279
|
+
const pathname = new URL(path6, "https://example.com").pathname;
|
|
280
|
+
for (const [name, application] of Object.entries(this.applications)) {
|
|
281
|
+
if (application.routing) {
|
|
282
|
+
for (const group of application.routing) {
|
|
283
|
+
for (const childPath of group.paths) {
|
|
284
|
+
const regexp = getRegexp(childPath);
|
|
285
|
+
if (regexp.test(pathname)) {
|
|
286
|
+
this.pathCache[path6] = name;
|
|
287
|
+
return name;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const defaultApplication = Object.entries(this.applications).find(
|
|
294
|
+
([, application]) => application.default
|
|
295
|
+
);
|
|
296
|
+
if (!defaultApplication) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
this.pathCache[path6] = defaultApplication[0];
|
|
300
|
+
return defaultApplication[0];
|
|
301
|
+
}
|
|
302
|
+
serialize() {
|
|
303
|
+
return this.serialized;
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// src/config/microfrontends-config/utils/get-config-from-env.ts
|
|
308
|
+
function getConfigStringFromEnv() {
|
|
309
|
+
const config = process.env.MFE_CONFIG;
|
|
310
|
+
if (!config) {
|
|
311
|
+
throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
|
|
312
|
+
type: "config",
|
|
313
|
+
subtype: "not_found_in_env"
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
return config;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// src/config/microfrontends-config/isomorphic/constants.ts
|
|
320
|
+
var DEFAULT_LOCAL_PROXY_PORT = 3024;
|
|
321
|
+
var MFE_APP_PORT_ENV = "MFE_APP_PORT";
|
|
322
|
+
var MFE_LOCAL_PROXY_PORT_ENV = "MFE_LOCAL_PROXY_PORT";
|
|
323
|
+
|
|
324
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-port.ts
|
|
325
|
+
function generatePortFromName({
|
|
326
|
+
name,
|
|
327
|
+
minPort = 3e3,
|
|
328
|
+
maxPort = 8e3
|
|
329
|
+
}) {
|
|
330
|
+
if (!name) {
|
|
331
|
+
throw new Error("Name is required to generate a port");
|
|
332
|
+
}
|
|
333
|
+
let hash = 0;
|
|
334
|
+
for (let i = 0; i < name.length; i++) {
|
|
335
|
+
hash = (hash << 5) - hash + name.charCodeAt(i);
|
|
336
|
+
hash |= 0;
|
|
337
|
+
}
|
|
338
|
+
hash = Math.abs(hash);
|
|
339
|
+
const range = maxPort - minPort;
|
|
340
|
+
const port = minPort + hash % range;
|
|
341
|
+
return port;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// src/config/microfrontends-config/isomorphic/host.ts
|
|
345
|
+
var Host = class {
|
|
346
|
+
constructor(hostConfig, options) {
|
|
347
|
+
if (typeof hostConfig === "string") {
|
|
348
|
+
({
|
|
349
|
+
protocol: this.protocol,
|
|
350
|
+
host: this.host,
|
|
351
|
+
port: this.port
|
|
352
|
+
} = Host.parseUrl(hostConfig));
|
|
353
|
+
} else {
|
|
354
|
+
const { protocol = "https", host, port } = hostConfig;
|
|
355
|
+
this.protocol = protocol;
|
|
356
|
+
this.host = host;
|
|
357
|
+
this.port = port;
|
|
358
|
+
}
|
|
359
|
+
this.local = options?.isLocal;
|
|
360
|
+
}
|
|
361
|
+
static parseUrl(url, defaultProtocol = "https") {
|
|
362
|
+
let hostToParse = url;
|
|
363
|
+
if (!/^https?:\/\//.exec(hostToParse)) {
|
|
364
|
+
hostToParse = `${defaultProtocol}://${hostToParse}`;
|
|
365
|
+
}
|
|
366
|
+
const parsed = new URL(hostToParse);
|
|
367
|
+
if (!parsed.hostname) {
|
|
368
|
+
throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
|
|
369
|
+
}
|
|
370
|
+
if (parsed.hash) {
|
|
371
|
+
throw new Error(
|
|
372
|
+
Host.getMicrofrontendsError(url, "cannot have a fragment")
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
if (parsed.username || parsed.password) {
|
|
376
|
+
throw new Error(
|
|
377
|
+
Host.getMicrofrontendsError(
|
|
378
|
+
url,
|
|
379
|
+
"cannot have authentication credentials (username and/or password)"
|
|
380
|
+
)
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
if (parsed.pathname !== "/") {
|
|
384
|
+
throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
|
|
385
|
+
}
|
|
386
|
+
if (parsed.search) {
|
|
387
|
+
throw new Error(
|
|
388
|
+
Host.getMicrofrontendsError(url, "cannot have query parameters")
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
const protocol = parsed.protocol.slice(0, -1);
|
|
392
|
+
return {
|
|
393
|
+
protocol,
|
|
394
|
+
host: parsed.hostname,
|
|
395
|
+
port: parsed.port ? Number.parseInt(parsed.port, 10) : void 0
|
|
396
|
+
};
|
|
528
397
|
}
|
|
529
|
-
|
|
530
|
-
return
|
|
398
|
+
static getMicrofrontendsError(url, message) {
|
|
399
|
+
return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
|
|
531
400
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
401
|
+
isLocal() {
|
|
402
|
+
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
403
|
+
}
|
|
404
|
+
toString() {
|
|
405
|
+
const url = this.toUrl();
|
|
406
|
+
return url.toString().replace(/\/$/, "");
|
|
407
|
+
}
|
|
408
|
+
toUrl() {
|
|
409
|
+
const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
|
|
410
|
+
return new URL(url);
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
var LocalHost = class extends Host {
|
|
414
|
+
constructor({
|
|
415
|
+
appName,
|
|
416
|
+
local
|
|
417
|
+
}) {
|
|
418
|
+
const portOverride = process.env[MFE_APP_PORT_ENV];
|
|
419
|
+
if (portOverride) {
|
|
420
|
+
const overridePort = Number.parseInt(portOverride, 10);
|
|
421
|
+
if (!Number.isNaN(overridePort) && overridePort > 0 && overridePort < 65536) {
|
|
422
|
+
super({
|
|
423
|
+
protocol: "http",
|
|
424
|
+
host: "localhost",
|
|
425
|
+
port: overridePort
|
|
426
|
+
});
|
|
427
|
+
return;
|
|
551
428
|
}
|
|
552
429
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
if (
|
|
557
|
-
|
|
430
|
+
let protocol;
|
|
431
|
+
let host;
|
|
432
|
+
let port;
|
|
433
|
+
if (typeof local === "number") {
|
|
434
|
+
port = local;
|
|
435
|
+
} else if (typeof local === "string") {
|
|
436
|
+
if (/^\d+$/.test(local)) {
|
|
437
|
+
port = Number.parseInt(local, 10);
|
|
438
|
+
} else {
|
|
439
|
+
const parsed = Host.parseUrl(local, "http");
|
|
440
|
+
protocol = parsed.protocol;
|
|
441
|
+
host = parsed.host;
|
|
442
|
+
port = parsed.port;
|
|
443
|
+
}
|
|
444
|
+
} else if (local) {
|
|
445
|
+
protocol = local.protocol;
|
|
446
|
+
host = local.host;
|
|
447
|
+
port = local.port;
|
|
558
448
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
449
|
+
super({
|
|
450
|
+
protocol: protocol ?? "http",
|
|
451
|
+
host: host ?? "localhost",
|
|
452
|
+
port: port ?? generatePortFromName({ name: appName })
|
|
453
|
+
});
|
|
564
454
|
}
|
|
565
455
|
};
|
|
566
456
|
|
|
457
|
+
// src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts
|
|
458
|
+
var import_md5 = __toESM(require("md5"), 1);
|
|
459
|
+
function hashApplicationName(name) {
|
|
460
|
+
if (!name) {
|
|
461
|
+
throw new Error("Application name is required to generate hash");
|
|
462
|
+
}
|
|
463
|
+
return (0, import_md5.default)(name).substring(0, 6).padStart(6, "0");
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
|
|
467
|
+
var PREFIX = "vc-ap";
|
|
468
|
+
function generateAssetPrefixFromName({
|
|
469
|
+
name
|
|
470
|
+
}) {
|
|
471
|
+
if (!name) {
|
|
472
|
+
throw new Error("Name is required to generate an asset prefix");
|
|
473
|
+
}
|
|
474
|
+
return `${PREFIX}-${hashApplicationName(name)}`;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts
|
|
478
|
+
function generateAutomationBypassEnvVarName({
|
|
479
|
+
name
|
|
480
|
+
}) {
|
|
481
|
+
return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
482
|
+
}
|
|
483
|
+
|
|
567
484
|
// src/config/microfrontends-config/isomorphic/validation.ts
|
|
568
485
|
var import_path_to_regexp2 = require("path-to-regexp");
|
|
569
486
|
var LIST_FORMATTER = new Intl.ListFormat("en", {
|
|
@@ -745,154 +662,6 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
|
|
|
745
662
|
}
|
|
746
663
|
};
|
|
747
664
|
|
|
748
|
-
// src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts
|
|
749
|
-
var import_md5 = __toESM(require("md5"), 1);
|
|
750
|
-
function hashApplicationName(name) {
|
|
751
|
-
if (!name) {
|
|
752
|
-
throw new Error("Application name is required to generate hash");
|
|
753
|
-
}
|
|
754
|
-
return (0, import_md5.default)(name).substring(0, 6).padStart(6, "0");
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
|
|
758
|
-
var PREFIX = "vc-ap";
|
|
759
|
-
function generateAssetPrefixFromName({
|
|
760
|
-
name
|
|
761
|
-
}) {
|
|
762
|
-
if (!name) {
|
|
763
|
-
throw new Error("Name is required to generate an asset prefix");
|
|
764
|
-
}
|
|
765
|
-
return `${PREFIX}-${hashApplicationName(name)}`;
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
// src/config/microfrontends-config/isomorphic/utils/generate-port.ts
|
|
769
|
-
function generatePortFromName({
|
|
770
|
-
name,
|
|
771
|
-
minPort = 3e3,
|
|
772
|
-
maxPort = 8e3
|
|
773
|
-
}) {
|
|
774
|
-
if (!name) {
|
|
775
|
-
throw new Error("Name is required to generate a port");
|
|
776
|
-
}
|
|
777
|
-
let hash = 0;
|
|
778
|
-
for (let i = 0; i < name.length; i++) {
|
|
779
|
-
hash = (hash << 5) - hash + name.charCodeAt(i);
|
|
780
|
-
hash |= 0;
|
|
781
|
-
}
|
|
782
|
-
hash = Math.abs(hash);
|
|
783
|
-
const range = maxPort - minPort;
|
|
784
|
-
const port = minPort + hash % range;
|
|
785
|
-
return port;
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
// src/config/microfrontends-config/isomorphic/host.ts
|
|
789
|
-
var Host = class {
|
|
790
|
-
constructor(hostConfig, options) {
|
|
791
|
-
if (typeof hostConfig === "string") {
|
|
792
|
-
({
|
|
793
|
-
protocol: this.protocol,
|
|
794
|
-
host: this.host,
|
|
795
|
-
port: this.port
|
|
796
|
-
} = Host.parseUrl(hostConfig));
|
|
797
|
-
} else {
|
|
798
|
-
const { protocol = "https", host, port } = hostConfig;
|
|
799
|
-
this.protocol = protocol;
|
|
800
|
-
this.host = host;
|
|
801
|
-
this.port = port;
|
|
802
|
-
}
|
|
803
|
-
this.local = options?.isLocal;
|
|
804
|
-
}
|
|
805
|
-
static parseUrl(url, defaultProtocol = "https") {
|
|
806
|
-
let hostToParse = url;
|
|
807
|
-
if (!/^https?:\/\//.exec(hostToParse)) {
|
|
808
|
-
hostToParse = `${defaultProtocol}://${hostToParse}`;
|
|
809
|
-
}
|
|
810
|
-
const parsed = new URL(hostToParse);
|
|
811
|
-
if (!parsed.hostname) {
|
|
812
|
-
throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
|
|
813
|
-
}
|
|
814
|
-
if (parsed.hash) {
|
|
815
|
-
throw new Error(
|
|
816
|
-
Host.getMicrofrontendsError(url, "cannot have a fragment")
|
|
817
|
-
);
|
|
818
|
-
}
|
|
819
|
-
if (parsed.username || parsed.password) {
|
|
820
|
-
throw new Error(
|
|
821
|
-
Host.getMicrofrontendsError(
|
|
822
|
-
url,
|
|
823
|
-
"cannot have authentication credentials (username and/or password)"
|
|
824
|
-
)
|
|
825
|
-
);
|
|
826
|
-
}
|
|
827
|
-
if (parsed.pathname !== "/") {
|
|
828
|
-
throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
|
|
829
|
-
}
|
|
830
|
-
if (parsed.search) {
|
|
831
|
-
throw new Error(
|
|
832
|
-
Host.getMicrofrontendsError(url, "cannot have query parameters")
|
|
833
|
-
);
|
|
834
|
-
}
|
|
835
|
-
const protocol = parsed.protocol.slice(0, -1);
|
|
836
|
-
return {
|
|
837
|
-
protocol,
|
|
838
|
-
host: parsed.hostname,
|
|
839
|
-
port: parsed.port ? Number.parseInt(parsed.port) : void 0
|
|
840
|
-
};
|
|
841
|
-
}
|
|
842
|
-
static getMicrofrontendsError(url, message) {
|
|
843
|
-
return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
|
|
844
|
-
}
|
|
845
|
-
isLocal() {
|
|
846
|
-
return this.local || this.host === "localhost" || this.host === "127.0.0.1";
|
|
847
|
-
}
|
|
848
|
-
toString() {
|
|
849
|
-
const url = this.toUrl();
|
|
850
|
-
return url.toString().replace(/\/$/, "");
|
|
851
|
-
}
|
|
852
|
-
toUrl() {
|
|
853
|
-
const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
|
|
854
|
-
return new URL(url);
|
|
855
|
-
}
|
|
856
|
-
};
|
|
857
|
-
var LocalHost = class extends Host {
|
|
858
|
-
constructor({
|
|
859
|
-
appName,
|
|
860
|
-
local
|
|
861
|
-
}) {
|
|
862
|
-
let protocol;
|
|
863
|
-
let host;
|
|
864
|
-
let port;
|
|
865
|
-
if (typeof local === "number") {
|
|
866
|
-
port = local;
|
|
867
|
-
} else if (typeof local === "string") {
|
|
868
|
-
if (/^\d+$/.test(local)) {
|
|
869
|
-
port = Number.parseInt(local);
|
|
870
|
-
} else {
|
|
871
|
-
const parsed = Host.parseUrl(local, "http");
|
|
872
|
-
protocol = parsed.protocol;
|
|
873
|
-
host = parsed.host;
|
|
874
|
-
port = parsed.port;
|
|
875
|
-
}
|
|
876
|
-
} else if (local) {
|
|
877
|
-
protocol = local.protocol;
|
|
878
|
-
host = local.host;
|
|
879
|
-
port = local.port;
|
|
880
|
-
}
|
|
881
|
-
super({
|
|
882
|
-
protocol: protocol ?? "http",
|
|
883
|
-
host: host ?? "localhost",
|
|
884
|
-
port: port ?? generatePortFromName({ name: appName })
|
|
885
|
-
});
|
|
886
|
-
}
|
|
887
|
-
};
|
|
888
|
-
|
|
889
|
-
// src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts
|
|
890
|
-
function generateAutomationBypassEnvVarName({
|
|
891
|
-
name
|
|
892
|
-
}) {
|
|
893
|
-
return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
894
|
-
}
|
|
895
|
-
|
|
896
665
|
// src/config/microfrontends-config/isomorphic/application.ts
|
|
897
666
|
var Application = class {
|
|
898
667
|
constructor(name, {
|
|
@@ -973,9 +742,6 @@ var ChildApplication = class extends Application {
|
|
|
973
742
|
}
|
|
974
743
|
};
|
|
975
744
|
|
|
976
|
-
// src/config/microfrontends-config/isomorphic/constants.ts
|
|
977
|
-
var DEFAULT_LOCAL_PROXY_PORT = 3024;
|
|
978
|
-
|
|
979
745
|
// src/config/microfrontends-config/isomorphic/index.ts
|
|
980
746
|
var MicrofrontendConfigIsomorphic = class {
|
|
981
747
|
constructor({
|
|
@@ -1019,7 +785,7 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
1019
785
|
};
|
|
1020
786
|
}
|
|
1021
787
|
static validate(config) {
|
|
1022
|
-
const c = typeof config === "string" ? (0,
|
|
788
|
+
const c = typeof config === "string" ? (0, import_jsonc_parser.parse)(config) : config;
|
|
1023
789
|
validateConfigPaths(c.applications);
|
|
1024
790
|
validateConfigDefaultApplication(c.applications);
|
|
1025
791
|
return c;
|
|
@@ -1028,7 +794,7 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
1028
794
|
cookies
|
|
1029
795
|
}) {
|
|
1030
796
|
return new MicrofrontendConfigIsomorphic({
|
|
1031
|
-
config: (0,
|
|
797
|
+
config: (0, import_jsonc_parser.parse)(getConfigStringFromEnv()),
|
|
1032
798
|
overrides: parseOverrides(cookies ?? [])
|
|
1033
799
|
});
|
|
1034
800
|
}
|
|
@@ -1094,9 +860,17 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
1094
860
|
return this.defaultApplication;
|
|
1095
861
|
}
|
|
1096
862
|
/**
|
|
1097
|
-
* Returns the configured port for the local proxy
|
|
863
|
+
* Returns the configured port for the local proxy.
|
|
864
|
+
* Can be overridden via MFE_LOCAL_PROXY_PORT environment variable.
|
|
1098
865
|
*/
|
|
1099
866
|
getLocalProxyPort() {
|
|
867
|
+
const portOverride = process.env[MFE_LOCAL_PROXY_PORT_ENV];
|
|
868
|
+
if (portOverride) {
|
|
869
|
+
const port = Number.parseInt(portOverride, 10);
|
|
870
|
+
if (!Number.isNaN(port) && port > 0 && port < 65536) {
|
|
871
|
+
return port;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
1100
874
|
return this.config.options?.localProxyPort ?? DEFAULT_LOCAL_PROXY_PORT;
|
|
1101
875
|
}
|
|
1102
876
|
toClientConfig(options) {
|
|
@@ -1134,36 +908,144 @@ var MicrofrontendConfigIsomorphic = class {
|
|
|
1134
908
|
}
|
|
1135
909
|
};
|
|
1136
910
|
|
|
911
|
+
// src/config/microfrontends/utils/find-config.ts
|
|
912
|
+
var import_node_fs = __toESM(require("fs"), 1);
|
|
913
|
+
var import_node_path = require("path");
|
|
914
|
+
|
|
915
|
+
// src/config/microfrontends/utils/get-config-file-name.ts
|
|
916
|
+
var DEFAULT_CONFIGURATION_FILENAMES = [
|
|
917
|
+
"microfrontends.json",
|
|
918
|
+
"microfrontends.jsonc"
|
|
919
|
+
];
|
|
920
|
+
function getPossibleConfigurationFilenames({
|
|
921
|
+
customConfigFilename
|
|
922
|
+
}) {
|
|
923
|
+
if (customConfigFilename) {
|
|
924
|
+
if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
|
|
925
|
+
throw new Error(
|
|
926
|
+
`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.`
|
|
927
|
+
);
|
|
928
|
+
}
|
|
929
|
+
return Array.from(
|
|
930
|
+
/* @__PURE__ */ new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES])
|
|
931
|
+
);
|
|
932
|
+
}
|
|
933
|
+
return DEFAULT_CONFIGURATION_FILENAMES;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
// src/config/microfrontends/utils/find-config.ts
|
|
937
|
+
function findConfig({
|
|
938
|
+
dir,
|
|
939
|
+
customConfigFilename
|
|
940
|
+
}) {
|
|
941
|
+
for (const filename of getPossibleConfigurationFilenames({
|
|
942
|
+
customConfigFilename
|
|
943
|
+
})) {
|
|
944
|
+
const maybeConfig = (0, import_node_path.join)(dir, filename);
|
|
945
|
+
if (import_node_fs.default.existsSync(maybeConfig)) {
|
|
946
|
+
return maybeConfig;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return null;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// src/config/microfrontends/utils/find-package-root.ts
|
|
953
|
+
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
954
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
955
|
+
var PACKAGE_JSON = "package.json";
|
|
956
|
+
function findPackageRoot(startDir) {
|
|
957
|
+
let currentDir = startDir || process.cwd();
|
|
958
|
+
while (currentDir !== import_node_path2.default.parse(currentDir).root) {
|
|
959
|
+
const pkgJsonPath = import_node_path2.default.join(currentDir, PACKAGE_JSON);
|
|
960
|
+
if (import_node_fs2.default.existsSync(pkgJsonPath)) {
|
|
961
|
+
return currentDir;
|
|
962
|
+
}
|
|
963
|
+
currentDir = import_node_path2.default.dirname(currentDir);
|
|
964
|
+
}
|
|
965
|
+
throw new Error(
|
|
966
|
+
`The root of the package that contains the \`package.json\` file for the \`${startDir}\` directory could not be found.`
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// src/config/microfrontends/utils/find-repository-root.ts
|
|
971
|
+
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
972
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
973
|
+
var GIT_DIRECTORY = ".git";
|
|
974
|
+
function hasGitDirectory(dir) {
|
|
975
|
+
const gitPath = import_node_path3.default.join(dir, GIT_DIRECTORY);
|
|
976
|
+
return import_node_fs3.default.existsSync(gitPath) && import_node_fs3.default.statSync(gitPath).isDirectory();
|
|
977
|
+
}
|
|
978
|
+
function hasPnpmWorkspaces(dir) {
|
|
979
|
+
return import_node_fs3.default.existsSync(import_node_path3.default.join(dir, "pnpm-workspace.yaml"));
|
|
980
|
+
}
|
|
981
|
+
function hasPackageJson(dir) {
|
|
982
|
+
return import_node_fs3.default.existsSync(import_node_path3.default.join(dir, "package.json"));
|
|
983
|
+
}
|
|
984
|
+
function findRepositoryRoot(startDir) {
|
|
985
|
+
if (process.env.NX_WORKSPACE_ROOT) {
|
|
986
|
+
return process.env.NX_WORKSPACE_ROOT;
|
|
987
|
+
}
|
|
988
|
+
let currentDir = startDir || process.cwd();
|
|
989
|
+
let lastPackageJsonDir = null;
|
|
990
|
+
while (currentDir !== import_node_path3.default.parse(currentDir).root) {
|
|
991
|
+
if (hasGitDirectory(currentDir) || hasPnpmWorkspaces(currentDir)) {
|
|
992
|
+
return currentDir;
|
|
993
|
+
}
|
|
994
|
+
if (hasPackageJson(currentDir)) {
|
|
995
|
+
lastPackageJsonDir = currentDir;
|
|
996
|
+
}
|
|
997
|
+
currentDir = import_node_path3.default.dirname(currentDir);
|
|
998
|
+
}
|
|
999
|
+
if (lastPackageJsonDir) {
|
|
1000
|
+
return lastPackageJsonDir;
|
|
1001
|
+
}
|
|
1002
|
+
throw new Error(
|
|
1003
|
+
`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.`
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1137
1007
|
// src/config/microfrontends/utils/get-application-context.ts
|
|
1138
|
-
var
|
|
1139
|
-
var
|
|
1008
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
1009
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
1140
1010
|
function getApplicationContext(opts) {
|
|
1141
1011
|
if (opts?.appName) {
|
|
1142
|
-
logger.debug(
|
|
1012
|
+
logger.debug(
|
|
1013
|
+
"[MFE Config] Application name from appName parameter:",
|
|
1014
|
+
opts.appName
|
|
1015
|
+
);
|
|
1143
1016
|
return { name: opts.appName };
|
|
1144
1017
|
}
|
|
1145
1018
|
if (process.env.VERCEL_PROJECT_NAME) {
|
|
1146
|
-
logger.debug(
|
|
1019
|
+
logger.debug(
|
|
1020
|
+
"[MFE Config] Application name from VERCEL_PROJECT_NAME:",
|
|
1021
|
+
process.env.VERCEL_PROJECT_NAME
|
|
1022
|
+
);
|
|
1147
1023
|
return {
|
|
1148
1024
|
name: process.env.VERCEL_PROJECT_NAME,
|
|
1149
1025
|
projectName: process.env.VERCEL_PROJECT_NAME
|
|
1150
1026
|
};
|
|
1151
1027
|
}
|
|
1152
1028
|
if (process.env.NX_TASK_TARGET_PROJECT) {
|
|
1153
|
-
logger.debug(
|
|
1029
|
+
logger.debug(
|
|
1030
|
+
"[MFE Config] Application name from NX_TASK_TARGET_PROJECT:",
|
|
1031
|
+
process.env.NX_TASK_TARGET_PROJECT
|
|
1032
|
+
);
|
|
1154
1033
|
return {
|
|
1155
1034
|
name: process.env.NX_TASK_TARGET_PROJECT,
|
|
1156
1035
|
packageJsonName: process.env.NX_TASK_TARGET_PROJECT
|
|
1157
1036
|
};
|
|
1158
1037
|
}
|
|
1159
1038
|
try {
|
|
1160
|
-
const vercelProjectJsonPath =
|
|
1161
|
-
|
|
1039
|
+
const vercelProjectJsonPath = import_node_fs4.default.readFileSync(
|
|
1040
|
+
import_node_path4.default.join(opts?.packageRoot || ".", ".vercel", "project.json"),
|
|
1162
1041
|
"utf-8"
|
|
1163
1042
|
);
|
|
1164
1043
|
const projectJson = JSON.parse(vercelProjectJsonPath);
|
|
1165
1044
|
if (projectJson.projectName) {
|
|
1166
|
-
logger.debug(
|
|
1045
|
+
logger.debug(
|
|
1046
|
+
"[MFE Config] Application name from .vercel/project.json:",
|
|
1047
|
+
projectJson.projectName
|
|
1048
|
+
);
|
|
1167
1049
|
return {
|
|
1168
1050
|
name: projectJson.projectName,
|
|
1169
1051
|
projectName: projectJson.projectName
|
|
@@ -1172,8 +1054,8 @@ function getApplicationContext(opts) {
|
|
|
1172
1054
|
} catch (_) {
|
|
1173
1055
|
}
|
|
1174
1056
|
try {
|
|
1175
|
-
const packageJsonString =
|
|
1176
|
-
|
|
1057
|
+
const packageJsonString = import_node_fs4.default.readFileSync(
|
|
1058
|
+
import_node_path4.default.join(opts?.packageRoot || ".", "package.json"),
|
|
1177
1059
|
"utf-8"
|
|
1178
1060
|
);
|
|
1179
1061
|
const packageJson = JSON.parse(packageJsonString);
|
|
@@ -1187,7 +1069,10 @@ function getApplicationContext(opts) {
|
|
|
1187
1069
|
}
|
|
1188
1070
|
);
|
|
1189
1071
|
}
|
|
1190
|
-
logger.debug(
|
|
1072
|
+
logger.debug(
|
|
1073
|
+
"[MFE Config] Application name from package.json:",
|
|
1074
|
+
packageJson.name
|
|
1075
|
+
);
|
|
1191
1076
|
return { name: packageJson.name, packageJsonName: packageJson.name };
|
|
1192
1077
|
} catch (err) {
|
|
1193
1078
|
throw MicrofrontendError.handle(err, {
|
|
@@ -1196,6 +1081,209 @@ function getApplicationContext(opts) {
|
|
|
1196
1081
|
}
|
|
1197
1082
|
}
|
|
1198
1083
|
|
|
1084
|
+
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
1085
|
+
var import_node_fs5 = require("fs");
|
|
1086
|
+
var import_node_path5 = require("path");
|
|
1087
|
+
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
1088
|
+
var import_jsonc_parser2 = require("jsonc-parser");
|
|
1089
|
+
var configCache = {};
|
|
1090
|
+
function findPackageWithMicrofrontendsConfig({
|
|
1091
|
+
repositoryRoot,
|
|
1092
|
+
applicationContext,
|
|
1093
|
+
customConfigFilename
|
|
1094
|
+
}) {
|
|
1095
|
+
const applicationName = applicationContext.name;
|
|
1096
|
+
logger.debug(
|
|
1097
|
+
"[MFE Config] Searching repository for configs containing application:",
|
|
1098
|
+
applicationName
|
|
1099
|
+
);
|
|
1100
|
+
try {
|
|
1101
|
+
const microfrontendsJsonPaths = import_fast_glob.default.globSync(
|
|
1102
|
+
`**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
|
|
1103
|
+
{
|
|
1104
|
+
cwd: repositoryRoot,
|
|
1105
|
+
absolute: true,
|
|
1106
|
+
onlyFiles: true,
|
|
1107
|
+
followSymbolicLinks: false,
|
|
1108
|
+
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
1109
|
+
}
|
|
1110
|
+
);
|
|
1111
|
+
logger.debug(
|
|
1112
|
+
"[MFE Config] Found",
|
|
1113
|
+
microfrontendsJsonPaths.length,
|
|
1114
|
+
"config file(s) in repository"
|
|
1115
|
+
);
|
|
1116
|
+
const matchingPaths = [];
|
|
1117
|
+
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
1118
|
+
if (doesApplicationExistInConfig(microfrontendsJsonPath, applicationName)) {
|
|
1119
|
+
matchingPaths.push(microfrontendsJsonPath);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
logger.debug(
|
|
1123
|
+
"[MFE Config] Total matching config files:",
|
|
1124
|
+
matchingPaths.length
|
|
1125
|
+
);
|
|
1126
|
+
if (matchingPaths.length > 1) {
|
|
1127
|
+
throw new MicrofrontendError(
|
|
1128
|
+
`Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
|
|
1129
|
+
${matchingPaths.join("\n \u2022 ")}`,
|
|
1130
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
if (matchingPaths.length === 0) {
|
|
1134
|
+
if (repositoryRoot && doesMisplacedConfigExist(
|
|
1135
|
+
repositoryRoot,
|
|
1136
|
+
applicationName,
|
|
1137
|
+
customConfigFilename
|
|
1138
|
+
)) {
|
|
1139
|
+
logger.debug(
|
|
1140
|
+
"[MFE Config] Found misplaced config in wrong .vercel directory in repository"
|
|
1141
|
+
);
|
|
1142
|
+
const misplacedConfigPath = (0, import_node_path5.join)(
|
|
1143
|
+
repositoryRoot,
|
|
1144
|
+
".vercel",
|
|
1145
|
+
customConfigFilename || "microfrontends.json"
|
|
1146
|
+
);
|
|
1147
|
+
throw new MicrofrontendError(
|
|
1148
|
+
`Unable to automatically infer the location of the \`microfrontends.json\` file.
|
|
1149
|
+
|
|
1150
|
+
A microfrontends config was found in the \`.vercel\` directory at the repository root: ${misplacedConfigPath}
|
|
1151
|
+
However, in a monorepo, the config file should be placed in the \`.vercel\` directory in your application directory instead.
|
|
1152
|
+
|
|
1153
|
+
To fix this:
|
|
1154
|
+
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
|
|
1155
|
+
2. If manually defined, move the config file to the \`.vercel\` directory in your application
|
|
1156
|
+
3. Alternatively, set the VC_MICROFRONTENDS_CONFIG environment variable to the correct path
|
|
1157
|
+
|
|
1158
|
+
For more information, see: https://vercel.com/docs/cli/project-linking`,
|
|
1159
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
let additionalErrorMessage = "";
|
|
1163
|
+
if (microfrontendsJsonPaths.length > 0) {
|
|
1164
|
+
if (!applicationContext.projectName) {
|
|
1165
|
+
additionalErrorMessage = `
|
|
1166
|
+
|
|
1167
|
+
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.`;
|
|
1168
|
+
} else {
|
|
1169
|
+
additionalErrorMessage = `
|
|
1170
|
+
|
|
1171
|
+
Names of applications in \`microfrontends.json\` must match the Vercel Project name (${applicationContext.projectName}).`;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
throw new MicrofrontendError(
|
|
1175
|
+
`Could not find a \`microfrontends.json\` file in the repository that contains the "${applicationName}" application.${additionalErrorMessage}
|
|
1176
|
+
|
|
1177
|
+
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.
|
|
1178
|
+
|
|
1179
|
+
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.
|
|
1180
|
+
|
|
1181
|
+
If you suspect this is thrown in error, please reach out to the Vercel team.`,
|
|
1182
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1183
|
+
);
|
|
1184
|
+
}
|
|
1185
|
+
const [packageJsonPath] = matchingPaths;
|
|
1186
|
+
return (0, import_node_path5.dirname)(packageJsonPath);
|
|
1187
|
+
} catch (error2) {
|
|
1188
|
+
if (error2 instanceof MicrofrontendError) {
|
|
1189
|
+
throw error2;
|
|
1190
|
+
}
|
|
1191
|
+
return null;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
function inferMicrofrontendsLocation(opts) {
|
|
1195
|
+
const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ""}`;
|
|
1196
|
+
if (configCache[cacheKey]) {
|
|
1197
|
+
return configCache[cacheKey];
|
|
1198
|
+
}
|
|
1199
|
+
const result = findPackageWithMicrofrontendsConfig(opts);
|
|
1200
|
+
if (!result) {
|
|
1201
|
+
throw new MicrofrontendError(
|
|
1202
|
+
`Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationContext.name}" starting in directory "${opts.repositoryRoot}".`,
|
|
1203
|
+
{ type: "config", subtype: "inference_failed" }
|
|
1204
|
+
);
|
|
1205
|
+
}
|
|
1206
|
+
configCache[cacheKey] = result;
|
|
1207
|
+
return result;
|
|
1208
|
+
}
|
|
1209
|
+
function existsSync(path6) {
|
|
1210
|
+
try {
|
|
1211
|
+
(0, import_node_fs5.statSync)(path6);
|
|
1212
|
+
return true;
|
|
1213
|
+
} catch (_) {
|
|
1214
|
+
return false;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
function doesMisplacedConfigExist(repositoryRoot, applicationName, customConfigFilename) {
|
|
1218
|
+
logger.debug(
|
|
1219
|
+
"[MFE Config] Looking for misplaced config in wrong .vercel directory"
|
|
1220
|
+
);
|
|
1221
|
+
const misplacedConfigPath = (0, import_node_path5.join)(
|
|
1222
|
+
repositoryRoot,
|
|
1223
|
+
".vercel",
|
|
1224
|
+
customConfigFilename || "microfrontends.json"
|
|
1225
|
+
);
|
|
1226
|
+
return existsSync(misplacedConfigPath) && doesApplicationExistInConfig(misplacedConfigPath, applicationName);
|
|
1227
|
+
}
|
|
1228
|
+
function doesApplicationExistInConfig(microfrontendsJsonPath, applicationName) {
|
|
1229
|
+
try {
|
|
1230
|
+
const microfrontendsJsonContent = (0, import_node_fs5.readFileSync)(
|
|
1231
|
+
microfrontendsJsonPath,
|
|
1232
|
+
"utf-8"
|
|
1233
|
+
);
|
|
1234
|
+
const microfrontendsJson = (0, import_jsonc_parser2.parse)(microfrontendsJsonContent);
|
|
1235
|
+
if (microfrontendsJson.applications[applicationName]) {
|
|
1236
|
+
logger.debug(
|
|
1237
|
+
"[MFE Config] Found application in config:",
|
|
1238
|
+
microfrontendsJsonPath
|
|
1239
|
+
);
|
|
1240
|
+
return true;
|
|
1241
|
+
}
|
|
1242
|
+
for (const [_, app] of Object.entries(microfrontendsJson.applications)) {
|
|
1243
|
+
if (app.packageName === applicationName) {
|
|
1244
|
+
logger.debug(
|
|
1245
|
+
"[MFE Config] Found application via packageName in config:",
|
|
1246
|
+
microfrontendsJsonPath
|
|
1247
|
+
);
|
|
1248
|
+
return true;
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
} catch (error2) {
|
|
1252
|
+
logger.debug("[MFE Config] Error checking application in config:", error2);
|
|
1253
|
+
}
|
|
1254
|
+
return false;
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
// src/config/microfrontends/utils/is-monorepo.ts
|
|
1258
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
1259
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
1260
|
+
function isMonorepo({
|
|
1261
|
+
repositoryRoot
|
|
1262
|
+
}) {
|
|
1263
|
+
try {
|
|
1264
|
+
if (import_node_fs6.default.existsSync(import_node_path6.default.join(repositoryRoot, "pnpm-workspace.yaml"))) {
|
|
1265
|
+
return true;
|
|
1266
|
+
}
|
|
1267
|
+
if (import_node_fs6.default.existsSync(import_node_path6.default.join(repositoryRoot, "vlt-workspaces.json"))) {
|
|
1268
|
+
return true;
|
|
1269
|
+
}
|
|
1270
|
+
if (process.env.NX_WORKSPACE_ROOT === import_node_path6.default.resolve(repositoryRoot)) {
|
|
1271
|
+
return true;
|
|
1272
|
+
}
|
|
1273
|
+
const packageJsonPath = import_node_path6.default.join(repositoryRoot, "package.json");
|
|
1274
|
+
if (!import_node_fs6.default.existsSync(packageJsonPath)) {
|
|
1275
|
+
return false;
|
|
1276
|
+
}
|
|
1277
|
+
const packageJson = JSON.parse(
|
|
1278
|
+
import_node_fs6.default.readFileSync(packageJsonPath, "utf-8")
|
|
1279
|
+
);
|
|
1280
|
+
return packageJson.workspaces !== void 0;
|
|
1281
|
+
} catch (error2) {
|
|
1282
|
+
logger.error("Error determining if repository is a monorepo", error2);
|
|
1283
|
+
return false;
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1199
1287
|
// src/config/microfrontends/server/utils/get-output-file-path.ts
|
|
1200
1288
|
var import_node_path7 = __toESM(require("path"), 1);
|
|
1201
1289
|
|
|
@@ -1209,8 +1297,8 @@ function getOutputFilePath() {
|
|
|
1209
1297
|
}
|
|
1210
1298
|
|
|
1211
1299
|
// src/config/microfrontends/server/validation.ts
|
|
1212
|
-
var import_jsonc_parser3 = require("jsonc-parser");
|
|
1213
1300
|
var import_ajv = require("ajv");
|
|
1301
|
+
var import_jsonc_parser3 = require("jsonc-parser");
|
|
1214
1302
|
|
|
1215
1303
|
// schema/schema.json
|
|
1216
1304
|
var schema_default = {
|
|
@@ -1238,9 +1326,7 @@ var schema_default = {
|
|
|
1238
1326
|
description: "Optional configuration options for the microfrontend."
|
|
1239
1327
|
}
|
|
1240
1328
|
},
|
|
1241
|
-
required: [
|
|
1242
|
-
"applications"
|
|
1243
|
-
],
|
|
1329
|
+
required: ["applications"],
|
|
1244
1330
|
additionalProperties: false,
|
|
1245
1331
|
description: "The microfrontends configuration schema. See https://vercel.com/docs/microfrontends/configuration."
|
|
1246
1332
|
},
|
|
@@ -1277,19 +1363,14 @@ var schema_default = {
|
|
|
1277
1363
|
description: "Development configuration for the default application."
|
|
1278
1364
|
}
|
|
1279
1365
|
},
|
|
1280
|
-
required: [
|
|
1281
|
-
"development"
|
|
1282
|
-
],
|
|
1366
|
+
required: ["development"],
|
|
1283
1367
|
additionalProperties: false
|
|
1284
1368
|
},
|
|
1285
1369
|
DefaultDevelopment: {
|
|
1286
1370
|
type: "object",
|
|
1287
1371
|
properties: {
|
|
1288
1372
|
local: {
|
|
1289
|
-
type: [
|
|
1290
|
-
"number",
|
|
1291
|
-
"string"
|
|
1292
|
-
],
|
|
1373
|
+
type: ["number", "string"],
|
|
1293
1374
|
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."
|
|
1294
1375
|
},
|
|
1295
1376
|
task: {
|
|
@@ -1301,9 +1382,7 @@ var schema_default = {
|
|
|
1301
1382
|
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."
|
|
1302
1383
|
}
|
|
1303
1384
|
},
|
|
1304
|
-
required: [
|
|
1305
|
-
"fallback"
|
|
1306
|
-
],
|
|
1385
|
+
required: ["fallback"],
|
|
1307
1386
|
additionalProperties: false
|
|
1308
1387
|
},
|
|
1309
1388
|
ChildApplication: {
|
|
@@ -1326,19 +1405,14 @@ var schema_default = {
|
|
|
1326
1405
|
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."
|
|
1327
1406
|
}
|
|
1328
1407
|
},
|
|
1329
|
-
required: [
|
|
1330
|
-
"routing"
|
|
1331
|
-
],
|
|
1408
|
+
required: ["routing"],
|
|
1332
1409
|
additionalProperties: false
|
|
1333
1410
|
},
|
|
1334
1411
|
ChildDevelopment: {
|
|
1335
1412
|
type: "object",
|
|
1336
1413
|
properties: {
|
|
1337
1414
|
local: {
|
|
1338
|
-
type: [
|
|
1339
|
-
"number",
|
|
1340
|
-
"string"
|
|
1341
|
-
],
|
|
1415
|
+
type: ["number", "string"],
|
|
1342
1416
|
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."
|
|
1343
1417
|
},
|
|
1344
1418
|
task: {
|
|
@@ -1378,9 +1452,7 @@ var schema_default = {
|
|
|
1378
1452
|
description: "A list of path expressions that are routed to this application. See https://vercel.com/docs/microfrontends/path-routing#supported-path-expressions."
|
|
1379
1453
|
}
|
|
1380
1454
|
},
|
|
1381
|
-
required: [
|
|
1382
|
-
"paths"
|
|
1383
|
-
],
|
|
1455
|
+
required: ["paths"],
|
|
1384
1456
|
additionalProperties: false,
|
|
1385
1457
|
description: "A group of paths that is routed to this application."
|
|
1386
1458
|
},
|