@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
|
@@ -78,10 +78,32 @@ function findConfig({
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
81
|
-
var import_node_path2 = require("path");
|
|
82
81
|
var import_node_fs2 = require("fs");
|
|
83
|
-
var
|
|
82
|
+
var import_node_path2 = require("path");
|
|
84
83
|
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
84
|
+
var import_jsonc_parser = require("jsonc-parser");
|
|
85
|
+
|
|
86
|
+
// src/bin/logger.ts
|
|
87
|
+
function debug(...args) {
|
|
88
|
+
if (process.env.MFE_DEBUG) {
|
|
89
|
+
console.log(...args);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function info(...args) {
|
|
93
|
+
console.log(...args);
|
|
94
|
+
}
|
|
95
|
+
function warn(...args) {
|
|
96
|
+
console.warn(...args);
|
|
97
|
+
}
|
|
98
|
+
function error(...args) {
|
|
99
|
+
console.error(...args);
|
|
100
|
+
}
|
|
101
|
+
var logger = {
|
|
102
|
+
debug,
|
|
103
|
+
info,
|
|
104
|
+
warn,
|
|
105
|
+
error
|
|
106
|
+
};
|
|
85
107
|
|
|
86
108
|
// src/config/errors.ts
|
|
87
109
|
var MicrofrontendError = class extends Error {
|
|
@@ -175,28 +197,6 @@ var MicrofrontendError = class extends Error {
|
|
|
175
197
|
}
|
|
176
198
|
};
|
|
177
199
|
|
|
178
|
-
// src/bin/logger.ts
|
|
179
|
-
function debug(...args) {
|
|
180
|
-
if (process.env.MFE_DEBUG) {
|
|
181
|
-
console.log(...args);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
function info(...args) {
|
|
185
|
-
console.log(...args);
|
|
186
|
-
}
|
|
187
|
-
function warn(...args) {
|
|
188
|
-
console.warn(...args);
|
|
189
|
-
}
|
|
190
|
-
function error(...args) {
|
|
191
|
-
console.error(...args);
|
|
192
|
-
}
|
|
193
|
-
var logger = {
|
|
194
|
-
debug,
|
|
195
|
-
info,
|
|
196
|
-
warn,
|
|
197
|
-
error
|
|
198
|
-
};
|
|
199
|
-
|
|
200
200
|
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
201
201
|
var configCache = {};
|
|
202
202
|
function findPackageWithMicrofrontendsConfig({
|
|
@@ -227,32 +227,8 @@ function findPackageWithMicrofrontendsConfig({
|
|
|
227
227
|
);
|
|
228
228
|
const matchingPaths = [];
|
|
229
229
|
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
microfrontendsJsonPath,
|
|
233
|
-
"utf-8"
|
|
234
|
-
);
|
|
235
|
-
const microfrontendsJson = (0, import_jsonc_parser.parse)(microfrontendsJsonContent);
|
|
236
|
-
if (microfrontendsJson.applications[applicationName]) {
|
|
237
|
-
logger.debug(
|
|
238
|
-
"[MFE Config] Found application in config:",
|
|
239
|
-
microfrontendsJsonPath
|
|
240
|
-
);
|
|
241
|
-
matchingPaths.push(microfrontendsJsonPath);
|
|
242
|
-
} else {
|
|
243
|
-
for (const [_, app] of Object.entries(
|
|
244
|
-
microfrontendsJson.applications
|
|
245
|
-
)) {
|
|
246
|
-
if (app.packageName === applicationName) {
|
|
247
|
-
logger.debug(
|
|
248
|
-
"[MFE Config] Found application via packageName in config:",
|
|
249
|
-
microfrontendsJsonPath
|
|
250
|
-
);
|
|
251
|
-
matchingPaths.push(microfrontendsJsonPath);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
} catch (error2) {
|
|
230
|
+
if (doesApplicationExistInConfig(microfrontendsJsonPath, applicationName)) {
|
|
231
|
+
matchingPaths.push(microfrontendsJsonPath);
|
|
256
232
|
}
|
|
257
233
|
}
|
|
258
234
|
logger.debug(
|
|
@@ -267,6 +243,34 @@ ${matchingPaths.join("\n \u2022 ")}`,
|
|
|
267
243
|
);
|
|
268
244
|
}
|
|
269
245
|
if (matchingPaths.length === 0) {
|
|
246
|
+
if (repositoryRoot && doesMisplacedConfigExist(
|
|
247
|
+
repositoryRoot,
|
|
248
|
+
applicationName,
|
|
249
|
+
customConfigFilename
|
|
250
|
+
)) {
|
|
251
|
+
logger.debug(
|
|
252
|
+
"[MFE Config] Found misplaced config in wrong .vercel directory in repository"
|
|
253
|
+
);
|
|
254
|
+
const misplacedConfigPath = (0, import_node_path2.join)(
|
|
255
|
+
repositoryRoot,
|
|
256
|
+
".vercel",
|
|
257
|
+
customConfigFilename || "microfrontends.json"
|
|
258
|
+
);
|
|
259
|
+
throw new MicrofrontendError(
|
|
260
|
+
`Unable to automatically infer the location of the \`microfrontends.json\` file.
|
|
261
|
+
|
|
262
|
+
A microfrontends config was found in the \`.vercel\` directory at the repository root: ${misplacedConfigPath}
|
|
263
|
+
However, in a monorepo, the config file should be placed in the \`.vercel\` directory in your application directory instead.
|
|
264
|
+
|
|
265
|
+
To fix this:
|
|
266
|
+
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
|
|
267
|
+
2. If manually defined, move the config file to the \`.vercel\` directory in your application
|
|
268
|
+
3. Alternatively, set the VC_MICROFRONTENDS_CONFIG environment variable to the correct path
|
|
269
|
+
|
|
270
|
+
For more information, see: https://vercel.com/docs/cli/project-linking`,
|
|
271
|
+
{ type: "config", subtype: "inference_failed" }
|
|
272
|
+
);
|
|
273
|
+
}
|
|
270
274
|
let additionalErrorMessage = "";
|
|
271
275
|
if (microfrontendsJsonPaths.length > 0) {
|
|
272
276
|
if (!applicationContext.projectName) {
|
|
@@ -314,6 +318,53 @@ function inferMicrofrontendsLocation(opts) {
|
|
|
314
318
|
configCache[cacheKey] = result;
|
|
315
319
|
return result;
|
|
316
320
|
}
|
|
321
|
+
function existsSync(path) {
|
|
322
|
+
try {
|
|
323
|
+
(0, import_node_fs2.statSync)(path);
|
|
324
|
+
return true;
|
|
325
|
+
} catch (_) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function doesMisplacedConfigExist(repositoryRoot, applicationName, customConfigFilename) {
|
|
330
|
+
logger.debug(
|
|
331
|
+
"[MFE Config] Looking for misplaced config in wrong .vercel directory"
|
|
332
|
+
);
|
|
333
|
+
const misplacedConfigPath = (0, import_node_path2.join)(
|
|
334
|
+
repositoryRoot,
|
|
335
|
+
".vercel",
|
|
336
|
+
customConfigFilename || "microfrontends.json"
|
|
337
|
+
);
|
|
338
|
+
return existsSync(misplacedConfigPath) && doesApplicationExistInConfig(misplacedConfigPath, applicationName);
|
|
339
|
+
}
|
|
340
|
+
function doesApplicationExistInConfig(microfrontendsJsonPath, applicationName) {
|
|
341
|
+
try {
|
|
342
|
+
const microfrontendsJsonContent = (0, import_node_fs2.readFileSync)(
|
|
343
|
+
microfrontendsJsonPath,
|
|
344
|
+
"utf-8"
|
|
345
|
+
);
|
|
346
|
+
const microfrontendsJson = (0, import_jsonc_parser.parse)(microfrontendsJsonContent);
|
|
347
|
+
if (microfrontendsJson.applications[applicationName]) {
|
|
348
|
+
logger.debug(
|
|
349
|
+
"[MFE Config] Found application in config:",
|
|
350
|
+
microfrontendsJsonPath
|
|
351
|
+
);
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
for (const [_, app] of Object.entries(microfrontendsJson.applications)) {
|
|
355
|
+
if (app.packageName === applicationName) {
|
|
356
|
+
logger.debug(
|
|
357
|
+
"[MFE Config] Found application via packageName in config:",
|
|
358
|
+
microfrontendsJsonPath
|
|
359
|
+
);
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
} catch (error2) {
|
|
364
|
+
logger.debug("[MFE Config] Error checking application in config:", error2);
|
|
365
|
+
}
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
317
368
|
// Annotate the CommonJS export names for ESM import in node:
|
|
318
369
|
0 && (module.exports = {
|
|
319
370
|
findConfig,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/microfrontends/utils/index.ts","../../src/config/microfrontends/utils/find-config.ts","../../src/config/microfrontends/utils/get-config-file-name.ts","../../src/config/microfrontends/utils/infer-microfrontends-location.ts","../../src/config/errors.ts","../../src/bin/logger.ts"],"sourcesContent":["export { findConfig } from './find-config';\nexport { inferMicrofrontendsLocation } from './infer-microfrontends-location';\nexport { getPossibleConfigurationFilenames } from './get-config-file-name';\n","import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\n\nexport function findConfig({\n dir,\n customConfigFilename,\n}: {\n dir: string;\n customConfigFilename: string | undefined;\n}): string | null {\n for (const filename of getPossibleConfigurationFilenames({\n customConfigFilename,\n })) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","// ordered by most likely to be the correct one\nconst DEFAULT_CONFIGURATION_FILENAMES = [\n 'microfrontends.json',\n 'microfrontends.jsonc',\n] as const;\n\nexport function getPossibleConfigurationFilenames({\n customConfigFilename,\n}: {\n // from env\n customConfigFilename: string | undefined;\n}) {\n if (customConfigFilename) {\n if (\n !customConfigFilename.endsWith('.json') &&\n !customConfigFilename.endsWith('.jsonc')\n ) {\n throw new Error(\n `Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}.` +\n ` The file name must end with '.json' or '.jsonc'.` +\n ` It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`,\n );\n }\n return Array.from(\n new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES]),\n );\n }\n return DEFAULT_CONFIGURATION_FILENAMES;\n}\n","import { dirname } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { parse } from 'jsonc-parser';\nimport fg from 'fast-glob';\nimport type { Config } from '../../schema/types';\nimport { MicrofrontendError } from '../../errors';\nimport { logger } from '../../../bin/logger';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\nimport type { ApplicationContext } from './get-application-context';\n\n// cache the path to default configuration to avoid having to walk the file system multiple times\nconst configCache: Record<string, string> = {};\n\ninterface FindDefaultMicrofrontendPackageArgs {\n repositoryRoot: string;\n applicationContext: ApplicationContext;\n customConfigFilename: string | undefined;\n}\n\n/**\n * Given a repository root and a package name, find the path to the package.json file with the\n * given name.\n *\n * This method uses globby to find all package.json files and then reads them in parallel\n */\nfunction findPackageWithMicrofrontendsConfig({\n repositoryRoot,\n applicationContext,\n customConfigFilename,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n const applicationName = applicationContext.name;\n logger.debug(\n '[MFE Config] Searching repository for configs containing application:',\n applicationName,\n );\n\n try {\n // eslint-disable-next-line import/no-named-as-default-member\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(',')}}`,\n {\n cwd: repositoryRoot,\n absolute: true,\n onlyFiles: true,\n followSymbolicLinks: false,\n ignore: ['**/node_modules/**', '**/.git/**'],\n },\n );\n\n logger.debug(\n '[MFE Config] Found',\n microfrontendsJsonPaths.length,\n 'config file(s) in repository',\n );\n\n const matchingPaths: string[] = [];\n for (const microfrontendsJsonPath of microfrontendsJsonPaths) {\n try {\n const microfrontendsJsonContent = readFileSync(\n microfrontendsJsonPath,\n 'utf-8',\n );\n const microfrontendsJson = parse(microfrontendsJsonContent) as Config;\n\n if (microfrontendsJson.applications[applicationName]) {\n logger.debug(\n '[MFE Config] Found application in config:',\n microfrontendsJsonPath,\n );\n matchingPaths.push(microfrontendsJsonPath);\n } else {\n for (const [_, app] of Object.entries(\n microfrontendsJson.applications,\n )) {\n if (app.packageName === applicationName) {\n logger.debug(\n '[MFE Config] Found application via packageName in config:',\n microfrontendsJsonPath,\n );\n matchingPaths.push(microfrontendsJsonPath);\n }\n }\n }\n } catch (error) {\n // malformed json most likely, skip this file\n }\n }\n\n logger.debug(\n '[MFE Config] Total matching config files:',\n matchingPaths.length,\n );\n\n if (matchingPaths.length > 1) {\n throw new MicrofrontendError(\n `Found multiple \\`microfrontends.json\\` files in the repository referencing the application \"${applicationName}\", but only one is allowed.\\n${matchingPaths.join('\\n • ')}`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n if (matchingPaths.length === 0) {\n let additionalErrorMessage = '';\n if (microfrontendsJsonPaths.length > 0) {\n if (!applicationContext.projectName) {\n additionalErrorMessage = `\\n\\nIf 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.`;\n } else {\n additionalErrorMessage = `\\n\\nNames of applications in \\`microfrontends.json\\` must match the Vercel Project name (${applicationContext.projectName}).`;\n }\n }\n throw new MicrofrontendError(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains the \"${applicationName}\" application.${additionalErrorMessage}\\n\\n` +\n `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.\\n\\n` +\n `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.\\n\\n` +\n `If you suspect this is thrown in error, please reach out to the Vercel team.`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n if (error instanceof MicrofrontendError) {\n throw error;\n }\n return null;\n }\n}\n\n/**\n * Given a repository root and a package name, find the path to the package directory with\n * a microfrontends config that contains the given name in its applications.\n */\nexport function inferMicrofrontendsLocation(\n opts: FindDefaultMicrofrontendPackageArgs,\n): string {\n // cache this with name to support multiple configurations in the same repository\n const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ''}`;\n\n // Check if we have a cached result\n if (configCache[cacheKey]) {\n return configCache[cacheKey];\n }\n\n const result = findPackageWithMicrofrontendsConfig(opts);\n\n if (!result) {\n throw new MicrofrontendError(\n `Could not infer the location of the \\`microfrontends.json\\` file for application \"${opts.applicationContext.name}\" starting in directory \"${opts.repositoryRoot}\".`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n // Cache the result\n configCache[cacheKey] = result;\n return result;\n}\n","export type MicrofrontendErrorType =\n | 'config'\n | 'packageJson'\n | 'vercelJson'\n | 'application'\n | 'unknown';\n\nexport type MicrofrontendErrorSubtype =\n | 'not_found'\n | 'inference_failed'\n | 'not_found_in_env'\n | 'invalid_asset_prefix'\n | 'invalid_main_path'\n | 'does_not_match_schema'\n | 'unable_to_read_file'\n | 'unsupported_validation_env'\n | 'unsupported_version'\n | 'invalid_path'\n | 'invalid_permissions'\n | 'invalid_syntax'\n | 'missing_microfrontend_config_path'\n | 'unsupported_operation';\n\n// A mapping of error types to their subtypes.\ninterface TypeToSubtype {\n application:\n | 'invalid_asset_prefix'\n | 'invalid_path'\n | 'multiple_package_managers'\n | 'not_found';\n config:\n | 'conflicting_paths'\n | 'depcrecated_field'\n | 'does_not_match_schema'\n | 'invalid_main_path'\n | 'invalid_preview_deployment_suffix'\n | 'multiple_default_applications'\n | 'no_default_application'\n | 'not_found_in_env'\n | 'not_found'\n | 'inference_failed'\n | 'unable_to_read_file'\n | 'invalid_syntax'\n | 'invalid_permissions'\n | 'unsupported_operation'\n | 'unsupported_validation_env'\n | 'unsupported_version';\n packageJson:\n | 'missing_field_name'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n vercelJson:\n | 'missing_field_microfrontend_config_path'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n unknown: never;\n}\n\nexport type MicrofrontendErrorSource =\n | '@vercel/microfrontends'\n | '@vercel/microfrontends/next'\n | 'fs'\n | 'ajv';\n\nexport interface MicrofrontendErrorOptions<T extends MicrofrontendErrorType> {\n cause?: unknown;\n source?: MicrofrontendErrorSource;\n type?: T;\n subtype?: TypeToSubtype[T];\n}\n\ninterface HandleOptions {\n fileName?: string;\n}\n\nexport class MicrofrontendError<\n T extends MicrofrontendErrorType = 'unknown',\n> extends Error {\n public source: MicrofrontendErrorSource;\n public type: T;\n public subtype?: TypeToSubtype[T];\n\n constructor(message: string, opts?: MicrofrontendErrorOptions<T>) {\n super(message, { cause: opts?.cause });\n this.name = 'MicrofrontendsError';\n this.source = opts?.source ?? '@vercel/microfrontends';\n this.type = opts?.type ?? ('unknown' as T);\n this.subtype = opts?.subtype;\n Error.captureStackTrace(this, MicrofrontendError);\n }\n\n isKnown(): boolean {\n return this.type !== 'unknown';\n }\n\n isUnknown(): boolean {\n return !this.isKnown();\n }\n\n /**\n * Converts an error to a MicrofrontendsError.\n * @param original - The original error to convert.\n * @returns The converted MicrofrontendsError.\n */\n static convert(\n original: Error,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (opts?.fileName) {\n const err = MicrofrontendError.convertFSError(original, opts.fileName);\n if (err) {\n return err;\n }\n }\n\n if (\n original.message.includes(\n 'Code generation from strings disallowed for this context',\n )\n ) {\n return new MicrofrontendError(original.message, {\n type: 'config',\n subtype: 'unsupported_validation_env',\n source: 'ajv',\n });\n }\n\n // unknown catch-all\n return new MicrofrontendError(original.message);\n }\n\n static convertFSError(\n original: Error,\n fileName: string,\n ): MicrofrontendError<MicrofrontendErrorType> | null {\n if (original instanceof Error && 'code' in original) {\n if (original.code === 'ENOENT') {\n return new MicrofrontendError(`Could not find \"${fileName}\"`, {\n type: 'config',\n subtype: 'unable_to_read_file',\n source: 'fs',\n });\n }\n if (original.code === 'EACCES') {\n return new MicrofrontendError(\n `Permission denied while accessing \"${fileName}\"`,\n {\n type: 'config',\n subtype: 'invalid_permissions',\n source: 'fs',\n },\n );\n }\n }\n\n if (original instanceof SyntaxError) {\n return new MicrofrontendError(\n `Failed to parse \"${fileName}\": Invalid JSON format.`,\n {\n type: 'config',\n subtype: 'invalid_syntax',\n source: 'fs',\n },\n );\n }\n\n return null;\n }\n\n /**\n * Handles an unknown error and returns a MicrofrontendsError instance.\n * @param err - The error to handle.\n * @returns A MicrofrontendsError instance.\n */\n static handle(\n err: unknown,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (err instanceof MicrofrontendError) {\n return err as MicrofrontendError<MicrofrontendErrorType>;\n }\n\n // handle Error instances\n if (err instanceof Error) {\n return MicrofrontendError.convert(err, opts);\n }\n\n // handle object errors\n if (typeof err === 'object' && err !== null) {\n if ('message' in err && typeof err.message === 'string') {\n return MicrofrontendError.convert(new Error(err.message), opts);\n }\n }\n\n return new MicrofrontendError('An unknown error occurred');\n }\n}\n","/* eslint-disable no-console */\n\nfunction debug(...args: unknown[]): void {\n if (process.env.MFE_DEBUG) {\n console.log(...args);\n }\n}\n\nfunction info(...args: unknown[]): void {\n console.log(...args);\n}\n\nfunction warn(...args: unknown[]): void {\n console.warn(...args);\n}\n\nfunction error(...args: unknown[]): void {\n console.error(...args);\n}\n\nexport const logger = {\n debug,\n info,\n warn,\n error,\n};\n"],"mappings":"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","names":["fs","import_node_path","import_node_fs","fg","error"]}
|
|
1
|
+
{"version":3,"sources":["../../src/config/microfrontends/utils/index.ts","../../src/config/microfrontends/utils/find-config.ts","../../src/config/microfrontends/utils/get-config-file-name.ts","../../src/config/microfrontends/utils/infer-microfrontends-location.ts","../../src/bin/logger.ts","../../src/config/errors.ts"],"sourcesContent":["export { findConfig } from './find-config';\nexport { getPossibleConfigurationFilenames } from './get-config-file-name';\nexport { inferMicrofrontendsLocation } from './infer-microfrontends-location';\n","import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\n\nexport function findConfig({\n dir,\n customConfigFilename,\n}: {\n dir: string;\n customConfigFilename: string | undefined;\n}): string | null {\n for (const filename of getPossibleConfigurationFilenames({\n customConfigFilename,\n })) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","// ordered by most likely to be the correct one\nconst DEFAULT_CONFIGURATION_FILENAMES = [\n 'microfrontends.json',\n 'microfrontends.jsonc',\n] as const;\n\nexport function getPossibleConfigurationFilenames({\n customConfigFilename,\n}: {\n // from env\n customConfigFilename: string | undefined;\n}) {\n if (customConfigFilename) {\n if (\n !customConfigFilename.endsWith('.json') &&\n !customConfigFilename.endsWith('.jsonc')\n ) {\n throw new Error(\n `Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}.` +\n ` The file name must end with '.json' or '.jsonc'.` +\n ` It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`,\n );\n }\n return Array.from(\n new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES]),\n );\n }\n return DEFAULT_CONFIGURATION_FILENAMES;\n}\n","import { readFileSync, statSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport fg from 'fast-glob';\nimport { parse } from 'jsonc-parser';\nimport { logger } from '../../../bin/logger';\nimport { MicrofrontendError } from '../../errors';\nimport type { Config } from '../../schema/types';\nimport type { ApplicationContext } from './get-application-context';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\n\n// cache the path to default configuration to avoid having to walk the file system multiple times\nconst configCache: Record<string, string> = {};\n\ninterface FindDefaultMicrofrontendPackageArgs {\n repositoryRoot: string;\n applicationContext: ApplicationContext;\n customConfigFilename: string | undefined;\n}\n\n/**\n * Given a repository root and a package name, find the path to the package.json file with the\n * given name.\n *\n * This method uses globby to find all package.json files and then reads them in parallel\n */\nfunction findPackageWithMicrofrontendsConfig({\n repositoryRoot,\n applicationContext,\n customConfigFilename,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n const applicationName = applicationContext.name;\n logger.debug(\n '[MFE Config] Searching repository for configs containing application:',\n applicationName,\n );\n\n try {\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(',')}}`,\n {\n cwd: repositoryRoot,\n absolute: true,\n onlyFiles: true,\n followSymbolicLinks: false,\n ignore: ['**/node_modules/**', '**/.git/**'],\n },\n );\n\n logger.debug(\n '[MFE Config] Found',\n microfrontendsJsonPaths.length,\n 'config file(s) in repository',\n );\n\n const matchingPaths: string[] = [];\n for (const microfrontendsJsonPath of microfrontendsJsonPaths) {\n if (\n doesApplicationExistInConfig(microfrontendsJsonPath, applicationName)\n ) {\n matchingPaths.push(microfrontendsJsonPath);\n }\n }\n\n logger.debug(\n '[MFE Config] Total matching config files:',\n matchingPaths.length,\n );\n\n if (matchingPaths.length > 1) {\n throw new MicrofrontendError(\n `Found multiple \\`microfrontends.json\\` files in the repository referencing the application \"${applicationName}\", but only one is allowed.\\n${matchingPaths.join('\\n • ')}`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n if (matchingPaths.length === 0) {\n if (\n repositoryRoot &&\n doesMisplacedConfigExist(\n repositoryRoot,\n applicationName,\n customConfigFilename,\n )\n ) {\n logger.debug(\n '[MFE Config] Found misplaced config in wrong .vercel directory in repository',\n );\n const misplacedConfigPath = join(\n repositoryRoot,\n '.vercel',\n customConfigFilename || 'microfrontends.json',\n );\n throw new MicrofrontendError(\n `Unable to automatically infer the location of the \\`microfrontends.json\\` file.\\n\\n` +\n `A microfrontends config was found in the \\`.vercel\\` directory at the repository root: ${misplacedConfigPath}\\n` +\n `However, in a monorepo, the config file should be placed in the \\`.vercel\\` directory in your application directory instead.\\n\\n` +\n `To fix this:\\n` +\n `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\\n` +\n `2. If manually defined, move the config file to the \\`.vercel\\` directory in your application\\n` +\n `3. Alternatively, set the VC_MICROFRONTENDS_CONFIG environment variable to the correct path\\n\\n` +\n `For more information, see: https://vercel.com/docs/cli/project-linking`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n let additionalErrorMessage = '';\n if (microfrontendsJsonPaths.length > 0) {\n if (!applicationContext.projectName) {\n additionalErrorMessage = `\\n\\nIf 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.`;\n } else {\n additionalErrorMessage = `\\n\\nNames of applications in \\`microfrontends.json\\` must match the Vercel Project name (${applicationContext.projectName}).`;\n }\n }\n throw new MicrofrontendError(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains the \"${applicationName}\" application.${additionalErrorMessage}\\n\\n` +\n `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.\\n\\n` +\n `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.\\n\\n` +\n `If you suspect this is thrown in error, please reach out to the Vercel team.`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n if (error instanceof MicrofrontendError) {\n throw error;\n }\n return null;\n }\n}\n\n/**\n * Given a repository root and a package name, find the path to the package directory with\n * a microfrontends config that contains the given name in its applications.\n */\nexport function inferMicrofrontendsLocation(\n opts: FindDefaultMicrofrontendPackageArgs,\n): string {\n // cache this with name to support multiple configurations in the same repository\n const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ''}`;\n\n // Check if we have a cached result\n if (configCache[cacheKey]) {\n return configCache[cacheKey];\n }\n\n const result = findPackageWithMicrofrontendsConfig(opts);\n\n if (!result) {\n throw new MicrofrontendError(\n `Could not infer the location of the \\`microfrontends.json\\` file for application \"${opts.applicationContext.name}\" starting in directory \"${opts.repositoryRoot}\".`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n // Cache the result\n configCache[cacheKey] = result;\n return result;\n}\n\nfunction existsSync(path: string): boolean {\n try {\n statSync(path);\n return true;\n } catch (_) {\n return false;\n }\n}\n\nfunction doesMisplacedConfigExist(\n repositoryRoot: string,\n applicationName: string,\n customConfigFilename: string | undefined,\n): boolean {\n logger.debug(\n '[MFE Config] Looking for misplaced config in wrong .vercel directory',\n );\n const misplacedConfigPath = join(\n repositoryRoot,\n '.vercel',\n customConfigFilename || 'microfrontends.json',\n );\n return (\n existsSync(misplacedConfigPath) &&\n doesApplicationExistInConfig(misplacedConfigPath, applicationName)\n );\n}\n\nfunction doesApplicationExistInConfig(\n microfrontendsJsonPath: string,\n applicationName: string,\n): boolean {\n try {\n const microfrontendsJsonContent = readFileSync(\n microfrontendsJsonPath,\n 'utf-8',\n );\n const microfrontendsJson = parse(microfrontendsJsonContent) as Config;\n\n if (microfrontendsJson.applications[applicationName]) {\n logger.debug(\n '[MFE Config] Found application in config:',\n microfrontendsJsonPath,\n );\n return true;\n }\n\n for (const [_, app] of Object.entries(microfrontendsJson.applications)) {\n if (app.packageName === applicationName) {\n logger.debug(\n '[MFE Config] Found application via packageName in config:',\n microfrontendsJsonPath,\n );\n return true;\n }\n }\n } catch (error) {\n logger.debug('[MFE Config] Error checking application in config:', error);\n // malformed json most likely, skip this file\n }\n return false;\n}\n","/* eslint-disable no-console */\n\nfunction debug(...args: unknown[]): void {\n if (process.env.MFE_DEBUG) {\n console.log(...args);\n }\n}\n\nfunction info(...args: unknown[]): void {\n console.log(...args);\n}\n\nfunction warn(...args: unknown[]): void {\n console.warn(...args);\n}\n\nfunction error(...args: unknown[]): void {\n console.error(...args);\n}\n\nexport const logger = {\n debug,\n info,\n warn,\n error,\n};\n","export type MicrofrontendErrorType =\n | 'config'\n | 'packageJson'\n | 'vercelJson'\n | 'application'\n | 'unknown';\n\nexport type MicrofrontendErrorSubtype =\n | 'not_found'\n | 'inference_failed'\n | 'not_found_in_env'\n | 'invalid_asset_prefix'\n | 'invalid_main_path'\n | 'does_not_match_schema'\n | 'unable_to_read_file'\n | 'unsupported_validation_env'\n | 'unsupported_version'\n | 'invalid_path'\n | 'invalid_permissions'\n | 'invalid_syntax'\n | 'missing_microfrontend_config_path'\n | 'unsupported_operation';\n\n// A mapping of error types to their subtypes.\ninterface TypeToSubtype {\n application:\n | 'invalid_asset_prefix'\n | 'invalid_path'\n | 'multiple_package_managers'\n | 'not_found';\n config:\n | 'conflicting_paths'\n | 'depcrecated_field'\n | 'does_not_match_schema'\n | 'invalid_main_path'\n | 'invalid_preview_deployment_suffix'\n | 'multiple_default_applications'\n | 'no_default_application'\n | 'not_found_in_env'\n | 'not_found'\n | 'inference_failed'\n | 'unable_to_read_file'\n | 'invalid_syntax'\n | 'invalid_permissions'\n | 'unsupported_operation'\n | 'unsupported_validation_env'\n | 'unsupported_version';\n packageJson:\n | 'missing_field_name'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n vercelJson:\n | 'missing_field_microfrontend_config_path'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n unknown: never;\n}\n\nexport type MicrofrontendErrorSource =\n | '@vercel/microfrontends'\n | '@vercel/microfrontends/next'\n | 'fs'\n | 'ajv';\n\nexport interface MicrofrontendErrorOptions<T extends MicrofrontendErrorType> {\n cause?: unknown;\n source?: MicrofrontendErrorSource;\n type?: T;\n subtype?: TypeToSubtype[T];\n}\n\ninterface HandleOptions {\n fileName?: string;\n}\n\nexport class MicrofrontendError<\n T extends MicrofrontendErrorType = 'unknown',\n> extends Error {\n public source: MicrofrontendErrorSource;\n public type: T;\n public subtype?: TypeToSubtype[T];\n\n constructor(message: string, opts?: MicrofrontendErrorOptions<T>) {\n super(message, { cause: opts?.cause });\n this.name = 'MicrofrontendsError';\n this.source = opts?.source ?? '@vercel/microfrontends';\n this.type = opts?.type ?? ('unknown' as T);\n this.subtype = opts?.subtype;\n Error.captureStackTrace(this, MicrofrontendError);\n }\n\n isKnown(): boolean {\n return this.type !== 'unknown';\n }\n\n isUnknown(): boolean {\n return !this.isKnown();\n }\n\n /**\n * Converts an error to a MicrofrontendsError.\n * @param original - The original error to convert.\n * @returns The converted MicrofrontendsError.\n */\n static convert(\n original: Error,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (opts?.fileName) {\n const err = MicrofrontendError.convertFSError(original, opts.fileName);\n if (err) {\n return err;\n }\n }\n\n if (\n original.message.includes(\n 'Code generation from strings disallowed for this context',\n )\n ) {\n return new MicrofrontendError(original.message, {\n type: 'config',\n subtype: 'unsupported_validation_env',\n source: 'ajv',\n });\n }\n\n // unknown catch-all\n return new MicrofrontendError(original.message);\n }\n\n static convertFSError(\n original: Error,\n fileName: string,\n ): MicrofrontendError<MicrofrontendErrorType> | null {\n if (original instanceof Error && 'code' in original) {\n if (original.code === 'ENOENT') {\n return new MicrofrontendError(`Could not find \"${fileName}\"`, {\n type: 'config',\n subtype: 'unable_to_read_file',\n source: 'fs',\n });\n }\n if (original.code === 'EACCES') {\n return new MicrofrontendError(\n `Permission denied while accessing \"${fileName}\"`,\n {\n type: 'config',\n subtype: 'invalid_permissions',\n source: 'fs',\n },\n );\n }\n }\n\n if (original instanceof SyntaxError) {\n return new MicrofrontendError(\n `Failed to parse \"${fileName}\": Invalid JSON format.`,\n {\n type: 'config',\n subtype: 'invalid_syntax',\n source: 'fs',\n },\n );\n }\n\n return null;\n }\n\n /**\n * Handles an unknown error and returns a MicrofrontendsError instance.\n * @param err - The error to handle.\n * @returns A MicrofrontendsError instance.\n */\n static handle(\n err: unknown,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (err instanceof MicrofrontendError) {\n return err as MicrofrontendError<MicrofrontendErrorType>;\n }\n\n // handle Error instances\n if (err instanceof Error) {\n return MicrofrontendError.convert(err, opts);\n }\n\n // handle object errors\n if (typeof err === 'object' && err !== null) {\n if ('message' in err && typeof err.message === 'string') {\n return MicrofrontendError.convert(new Error(err.message), opts);\n }\n }\n\n return new MicrofrontendError('An unknown error occurred');\n }\n}\n"],"mappings":"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","names":["fs","import_node_fs","import_node_path","fg","error"]}
|
|
@@ -5,6 +5,10 @@ declare function findConfig({ dir, customConfigFilename, }: {
|
|
|
5
5
|
customConfigFilename: string | undefined;
|
|
6
6
|
}): string | null;
|
|
7
7
|
|
|
8
|
+
declare function getPossibleConfigurationFilenames({ customConfigFilename, }: {
|
|
9
|
+
customConfigFilename: string | undefined;
|
|
10
|
+
}): string[] | readonly ["microfrontends.json", "microfrontends.jsonc"];
|
|
11
|
+
|
|
8
12
|
interface FindDefaultMicrofrontendPackageArgs {
|
|
9
13
|
repositoryRoot: string;
|
|
10
14
|
applicationContext: ApplicationContext;
|
|
@@ -16,8 +20,4 @@ interface FindDefaultMicrofrontendPackageArgs {
|
|
|
16
20
|
*/
|
|
17
21
|
declare function inferMicrofrontendsLocation(opts: FindDefaultMicrofrontendPackageArgs): string;
|
|
18
22
|
|
|
19
|
-
declare function getPossibleConfigurationFilenames({ customConfigFilename, }: {
|
|
20
|
-
customConfigFilename: string | undefined;
|
|
21
|
-
}): string[] | readonly ["microfrontends.json", "microfrontends.jsonc"];
|
|
22
|
-
|
|
23
23
|
export { findConfig, getPossibleConfigurationFilenames, inferMicrofrontendsLocation };
|
|
@@ -40,10 +40,32 @@ function findConfig({
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
import { parse } from "jsonc-parser";
|
|
43
|
+
import { readFileSync, statSync } from "node:fs";
|
|
44
|
+
import { dirname, join as join2 } from "node:path";
|
|
46
45
|
import fg from "fast-glob";
|
|
46
|
+
import { parse } from "jsonc-parser";
|
|
47
|
+
|
|
48
|
+
// src/bin/logger.ts
|
|
49
|
+
function debug(...args) {
|
|
50
|
+
if (process.env.MFE_DEBUG) {
|
|
51
|
+
console.log(...args);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function info(...args) {
|
|
55
|
+
console.log(...args);
|
|
56
|
+
}
|
|
57
|
+
function warn(...args) {
|
|
58
|
+
console.warn(...args);
|
|
59
|
+
}
|
|
60
|
+
function error(...args) {
|
|
61
|
+
console.error(...args);
|
|
62
|
+
}
|
|
63
|
+
var logger = {
|
|
64
|
+
debug,
|
|
65
|
+
info,
|
|
66
|
+
warn,
|
|
67
|
+
error
|
|
68
|
+
};
|
|
47
69
|
|
|
48
70
|
// src/config/errors.ts
|
|
49
71
|
var MicrofrontendError = class extends Error {
|
|
@@ -137,28 +159,6 @@ var MicrofrontendError = class extends Error {
|
|
|
137
159
|
}
|
|
138
160
|
};
|
|
139
161
|
|
|
140
|
-
// src/bin/logger.ts
|
|
141
|
-
function debug(...args) {
|
|
142
|
-
if (process.env.MFE_DEBUG) {
|
|
143
|
-
console.log(...args);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
function info(...args) {
|
|
147
|
-
console.log(...args);
|
|
148
|
-
}
|
|
149
|
-
function warn(...args) {
|
|
150
|
-
console.warn(...args);
|
|
151
|
-
}
|
|
152
|
-
function error(...args) {
|
|
153
|
-
console.error(...args);
|
|
154
|
-
}
|
|
155
|
-
var logger = {
|
|
156
|
-
debug,
|
|
157
|
-
info,
|
|
158
|
-
warn,
|
|
159
|
-
error
|
|
160
|
-
};
|
|
161
|
-
|
|
162
162
|
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
163
163
|
var configCache = {};
|
|
164
164
|
function findPackageWithMicrofrontendsConfig({
|
|
@@ -189,32 +189,8 @@ function findPackageWithMicrofrontendsConfig({
|
|
|
189
189
|
);
|
|
190
190
|
const matchingPaths = [];
|
|
191
191
|
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
microfrontendsJsonPath,
|
|
195
|
-
"utf-8"
|
|
196
|
-
);
|
|
197
|
-
const microfrontendsJson = parse(microfrontendsJsonContent);
|
|
198
|
-
if (microfrontendsJson.applications[applicationName]) {
|
|
199
|
-
logger.debug(
|
|
200
|
-
"[MFE Config] Found application in config:",
|
|
201
|
-
microfrontendsJsonPath
|
|
202
|
-
);
|
|
203
|
-
matchingPaths.push(microfrontendsJsonPath);
|
|
204
|
-
} else {
|
|
205
|
-
for (const [_, app] of Object.entries(
|
|
206
|
-
microfrontendsJson.applications
|
|
207
|
-
)) {
|
|
208
|
-
if (app.packageName === applicationName) {
|
|
209
|
-
logger.debug(
|
|
210
|
-
"[MFE Config] Found application via packageName in config:",
|
|
211
|
-
microfrontendsJsonPath
|
|
212
|
-
);
|
|
213
|
-
matchingPaths.push(microfrontendsJsonPath);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
} catch (error2) {
|
|
192
|
+
if (doesApplicationExistInConfig(microfrontendsJsonPath, applicationName)) {
|
|
193
|
+
matchingPaths.push(microfrontendsJsonPath);
|
|
218
194
|
}
|
|
219
195
|
}
|
|
220
196
|
logger.debug(
|
|
@@ -229,6 +205,34 @@ ${matchingPaths.join("\n \u2022 ")}`,
|
|
|
229
205
|
);
|
|
230
206
|
}
|
|
231
207
|
if (matchingPaths.length === 0) {
|
|
208
|
+
if (repositoryRoot && doesMisplacedConfigExist(
|
|
209
|
+
repositoryRoot,
|
|
210
|
+
applicationName,
|
|
211
|
+
customConfigFilename
|
|
212
|
+
)) {
|
|
213
|
+
logger.debug(
|
|
214
|
+
"[MFE Config] Found misplaced config in wrong .vercel directory in repository"
|
|
215
|
+
);
|
|
216
|
+
const misplacedConfigPath = join2(
|
|
217
|
+
repositoryRoot,
|
|
218
|
+
".vercel",
|
|
219
|
+
customConfigFilename || "microfrontends.json"
|
|
220
|
+
);
|
|
221
|
+
throw new MicrofrontendError(
|
|
222
|
+
`Unable to automatically infer the location of the \`microfrontends.json\` file.
|
|
223
|
+
|
|
224
|
+
A microfrontends config was found in the \`.vercel\` directory at the repository root: ${misplacedConfigPath}
|
|
225
|
+
However, in a monorepo, the config file should be placed in the \`.vercel\` directory in your application directory instead.
|
|
226
|
+
|
|
227
|
+
To fix this:
|
|
228
|
+
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
|
|
229
|
+
2. If manually defined, move the config file to the \`.vercel\` directory in your application
|
|
230
|
+
3. Alternatively, set the VC_MICROFRONTENDS_CONFIG environment variable to the correct path
|
|
231
|
+
|
|
232
|
+
For more information, see: https://vercel.com/docs/cli/project-linking`,
|
|
233
|
+
{ type: "config", subtype: "inference_failed" }
|
|
234
|
+
);
|
|
235
|
+
}
|
|
232
236
|
let additionalErrorMessage = "";
|
|
233
237
|
if (microfrontendsJsonPaths.length > 0) {
|
|
234
238
|
if (!applicationContext.projectName) {
|
|
@@ -276,6 +280,53 @@ function inferMicrofrontendsLocation(opts) {
|
|
|
276
280
|
configCache[cacheKey] = result;
|
|
277
281
|
return result;
|
|
278
282
|
}
|
|
283
|
+
function existsSync(path) {
|
|
284
|
+
try {
|
|
285
|
+
statSync(path);
|
|
286
|
+
return true;
|
|
287
|
+
} catch (_) {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function doesMisplacedConfigExist(repositoryRoot, applicationName, customConfigFilename) {
|
|
292
|
+
logger.debug(
|
|
293
|
+
"[MFE Config] Looking for misplaced config in wrong .vercel directory"
|
|
294
|
+
);
|
|
295
|
+
const misplacedConfigPath = join2(
|
|
296
|
+
repositoryRoot,
|
|
297
|
+
".vercel",
|
|
298
|
+
customConfigFilename || "microfrontends.json"
|
|
299
|
+
);
|
|
300
|
+
return existsSync(misplacedConfigPath) && doesApplicationExistInConfig(misplacedConfigPath, applicationName);
|
|
301
|
+
}
|
|
302
|
+
function doesApplicationExistInConfig(microfrontendsJsonPath, applicationName) {
|
|
303
|
+
try {
|
|
304
|
+
const microfrontendsJsonContent = readFileSync(
|
|
305
|
+
microfrontendsJsonPath,
|
|
306
|
+
"utf-8"
|
|
307
|
+
);
|
|
308
|
+
const microfrontendsJson = parse(microfrontendsJsonContent);
|
|
309
|
+
if (microfrontendsJson.applications[applicationName]) {
|
|
310
|
+
logger.debug(
|
|
311
|
+
"[MFE Config] Found application in config:",
|
|
312
|
+
microfrontendsJsonPath
|
|
313
|
+
);
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
for (const [_, app] of Object.entries(microfrontendsJson.applications)) {
|
|
317
|
+
if (app.packageName === applicationName) {
|
|
318
|
+
logger.debug(
|
|
319
|
+
"[MFE Config] Found application via packageName in config:",
|
|
320
|
+
microfrontendsJsonPath
|
|
321
|
+
);
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
} catch (error2) {
|
|
326
|
+
logger.debug("[MFE Config] Error checking application in config:", error2);
|
|
327
|
+
}
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
279
330
|
export {
|
|
280
331
|
findConfig,
|
|
281
332
|
getPossibleConfigurationFilenames,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/microfrontends/utils/find-config.ts","../../src/config/microfrontends/utils/get-config-file-name.ts","../../src/config/microfrontends/utils/infer-microfrontends-location.ts","../../src/config/errors.ts","../../src/bin/logger.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\n\nexport function findConfig({\n dir,\n customConfigFilename,\n}: {\n dir: string;\n customConfigFilename: string | undefined;\n}): string | null {\n for (const filename of getPossibleConfigurationFilenames({\n customConfigFilename,\n })) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","// ordered by most likely to be the correct one\nconst DEFAULT_CONFIGURATION_FILENAMES = [\n 'microfrontends.json',\n 'microfrontends.jsonc',\n] as const;\n\nexport function getPossibleConfigurationFilenames({\n customConfigFilename,\n}: {\n // from env\n customConfigFilename: string | undefined;\n}) {\n if (customConfigFilename) {\n if (\n !customConfigFilename.endsWith('.json') &&\n !customConfigFilename.endsWith('.jsonc')\n ) {\n throw new Error(\n `Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}.` +\n ` The file name must end with '.json' or '.jsonc'.` +\n ` It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`,\n );\n }\n return Array.from(\n new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES]),\n );\n }\n return DEFAULT_CONFIGURATION_FILENAMES;\n}\n","import { dirname } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { parse } from 'jsonc-parser';\nimport fg from 'fast-glob';\nimport type { Config } from '../../schema/types';\nimport { MicrofrontendError } from '../../errors';\nimport { logger } from '../../../bin/logger';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\nimport type { ApplicationContext } from './get-application-context';\n\n// cache the path to default configuration to avoid having to walk the file system multiple times\nconst configCache: Record<string, string> = {};\n\ninterface FindDefaultMicrofrontendPackageArgs {\n repositoryRoot: string;\n applicationContext: ApplicationContext;\n customConfigFilename: string | undefined;\n}\n\n/**\n * Given a repository root and a package name, find the path to the package.json file with the\n * given name.\n *\n * This method uses globby to find all package.json files and then reads them in parallel\n */\nfunction findPackageWithMicrofrontendsConfig({\n repositoryRoot,\n applicationContext,\n customConfigFilename,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n const applicationName = applicationContext.name;\n logger.debug(\n '[MFE Config] Searching repository for configs containing application:',\n applicationName,\n );\n\n try {\n // eslint-disable-next-line import/no-named-as-default-member\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(',')}}`,\n {\n cwd: repositoryRoot,\n absolute: true,\n onlyFiles: true,\n followSymbolicLinks: false,\n ignore: ['**/node_modules/**', '**/.git/**'],\n },\n );\n\n logger.debug(\n '[MFE Config] Found',\n microfrontendsJsonPaths.length,\n 'config file(s) in repository',\n );\n\n const matchingPaths: string[] = [];\n for (const microfrontendsJsonPath of microfrontendsJsonPaths) {\n try {\n const microfrontendsJsonContent = readFileSync(\n microfrontendsJsonPath,\n 'utf-8',\n );\n const microfrontendsJson = parse(microfrontendsJsonContent) as Config;\n\n if (microfrontendsJson.applications[applicationName]) {\n logger.debug(\n '[MFE Config] Found application in config:',\n microfrontendsJsonPath,\n );\n matchingPaths.push(microfrontendsJsonPath);\n } else {\n for (const [_, app] of Object.entries(\n microfrontendsJson.applications,\n )) {\n if (app.packageName === applicationName) {\n logger.debug(\n '[MFE Config] Found application via packageName in config:',\n microfrontendsJsonPath,\n );\n matchingPaths.push(microfrontendsJsonPath);\n }\n }\n }\n } catch (error) {\n // malformed json most likely, skip this file\n }\n }\n\n logger.debug(\n '[MFE Config] Total matching config files:',\n matchingPaths.length,\n );\n\n if (matchingPaths.length > 1) {\n throw new MicrofrontendError(\n `Found multiple \\`microfrontends.json\\` files in the repository referencing the application \"${applicationName}\", but only one is allowed.\\n${matchingPaths.join('\\n • ')}`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n if (matchingPaths.length === 0) {\n let additionalErrorMessage = '';\n if (microfrontendsJsonPaths.length > 0) {\n if (!applicationContext.projectName) {\n additionalErrorMessage = `\\n\\nIf 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.`;\n } else {\n additionalErrorMessage = `\\n\\nNames of applications in \\`microfrontends.json\\` must match the Vercel Project name (${applicationContext.projectName}).`;\n }\n }\n throw new MicrofrontendError(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains the \"${applicationName}\" application.${additionalErrorMessage}\\n\\n` +\n `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.\\n\\n` +\n `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.\\n\\n` +\n `If you suspect this is thrown in error, please reach out to the Vercel team.`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n if (error instanceof MicrofrontendError) {\n throw error;\n }\n return null;\n }\n}\n\n/**\n * Given a repository root and a package name, find the path to the package directory with\n * a microfrontends config that contains the given name in its applications.\n */\nexport function inferMicrofrontendsLocation(\n opts: FindDefaultMicrofrontendPackageArgs,\n): string {\n // cache this with name to support multiple configurations in the same repository\n const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ''}`;\n\n // Check if we have a cached result\n if (configCache[cacheKey]) {\n return configCache[cacheKey];\n }\n\n const result = findPackageWithMicrofrontendsConfig(opts);\n\n if (!result) {\n throw new MicrofrontendError(\n `Could not infer the location of the \\`microfrontends.json\\` file for application \"${opts.applicationContext.name}\" starting in directory \"${opts.repositoryRoot}\".`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n // Cache the result\n configCache[cacheKey] = result;\n return result;\n}\n","export type MicrofrontendErrorType =\n | 'config'\n | 'packageJson'\n | 'vercelJson'\n | 'application'\n | 'unknown';\n\nexport type MicrofrontendErrorSubtype =\n | 'not_found'\n | 'inference_failed'\n | 'not_found_in_env'\n | 'invalid_asset_prefix'\n | 'invalid_main_path'\n | 'does_not_match_schema'\n | 'unable_to_read_file'\n | 'unsupported_validation_env'\n | 'unsupported_version'\n | 'invalid_path'\n | 'invalid_permissions'\n | 'invalid_syntax'\n | 'missing_microfrontend_config_path'\n | 'unsupported_operation';\n\n// A mapping of error types to their subtypes.\ninterface TypeToSubtype {\n application:\n | 'invalid_asset_prefix'\n | 'invalid_path'\n | 'multiple_package_managers'\n | 'not_found';\n config:\n | 'conflicting_paths'\n | 'depcrecated_field'\n | 'does_not_match_schema'\n | 'invalid_main_path'\n | 'invalid_preview_deployment_suffix'\n | 'multiple_default_applications'\n | 'no_default_application'\n | 'not_found_in_env'\n | 'not_found'\n | 'inference_failed'\n | 'unable_to_read_file'\n | 'invalid_syntax'\n | 'invalid_permissions'\n | 'unsupported_operation'\n | 'unsupported_validation_env'\n | 'unsupported_version';\n packageJson:\n | 'missing_field_name'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n vercelJson:\n | 'missing_field_microfrontend_config_path'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n unknown: never;\n}\n\nexport type MicrofrontendErrorSource =\n | '@vercel/microfrontends'\n | '@vercel/microfrontends/next'\n | 'fs'\n | 'ajv';\n\nexport interface MicrofrontendErrorOptions<T extends MicrofrontendErrorType> {\n cause?: unknown;\n source?: MicrofrontendErrorSource;\n type?: T;\n subtype?: TypeToSubtype[T];\n}\n\ninterface HandleOptions {\n fileName?: string;\n}\n\nexport class MicrofrontendError<\n T extends MicrofrontendErrorType = 'unknown',\n> extends Error {\n public source: MicrofrontendErrorSource;\n public type: T;\n public subtype?: TypeToSubtype[T];\n\n constructor(message: string, opts?: MicrofrontendErrorOptions<T>) {\n super(message, { cause: opts?.cause });\n this.name = 'MicrofrontendsError';\n this.source = opts?.source ?? '@vercel/microfrontends';\n this.type = opts?.type ?? ('unknown' as T);\n this.subtype = opts?.subtype;\n Error.captureStackTrace(this, MicrofrontendError);\n }\n\n isKnown(): boolean {\n return this.type !== 'unknown';\n }\n\n isUnknown(): boolean {\n return !this.isKnown();\n }\n\n /**\n * Converts an error to a MicrofrontendsError.\n * @param original - The original error to convert.\n * @returns The converted MicrofrontendsError.\n */\n static convert(\n original: Error,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (opts?.fileName) {\n const err = MicrofrontendError.convertFSError(original, opts.fileName);\n if (err) {\n return err;\n }\n }\n\n if (\n original.message.includes(\n 'Code generation from strings disallowed for this context',\n )\n ) {\n return new MicrofrontendError(original.message, {\n type: 'config',\n subtype: 'unsupported_validation_env',\n source: 'ajv',\n });\n }\n\n // unknown catch-all\n return new MicrofrontendError(original.message);\n }\n\n static convertFSError(\n original: Error,\n fileName: string,\n ): MicrofrontendError<MicrofrontendErrorType> | null {\n if (original instanceof Error && 'code' in original) {\n if (original.code === 'ENOENT') {\n return new MicrofrontendError(`Could not find \"${fileName}\"`, {\n type: 'config',\n subtype: 'unable_to_read_file',\n source: 'fs',\n });\n }\n if (original.code === 'EACCES') {\n return new MicrofrontendError(\n `Permission denied while accessing \"${fileName}\"`,\n {\n type: 'config',\n subtype: 'invalid_permissions',\n source: 'fs',\n },\n );\n }\n }\n\n if (original instanceof SyntaxError) {\n return new MicrofrontendError(\n `Failed to parse \"${fileName}\": Invalid JSON format.`,\n {\n type: 'config',\n subtype: 'invalid_syntax',\n source: 'fs',\n },\n );\n }\n\n return null;\n }\n\n /**\n * Handles an unknown error and returns a MicrofrontendsError instance.\n * @param err - The error to handle.\n * @returns A MicrofrontendsError instance.\n */\n static handle(\n err: unknown,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (err instanceof MicrofrontendError) {\n return err as MicrofrontendError<MicrofrontendErrorType>;\n }\n\n // handle Error instances\n if (err instanceof Error) {\n return MicrofrontendError.convert(err, opts);\n }\n\n // handle object errors\n if (typeof err === 'object' && err !== null) {\n if ('message' in err && typeof err.message === 'string') {\n return MicrofrontendError.convert(new Error(err.message), opts);\n }\n }\n\n return new MicrofrontendError('An unknown error occurred');\n }\n}\n","/* eslint-disable no-console */\n\nfunction debug(...args: unknown[]): void {\n if (process.env.MFE_DEBUG) {\n console.log(...args);\n }\n}\n\nfunction info(...args: unknown[]): void {\n console.log(...args);\n}\n\nfunction warn(...args: unknown[]): void {\n console.warn(...args);\n}\n\nfunction error(...args: unknown[]): void {\n console.error(...args);\n}\n\nexport const logger = {\n debug,\n info,\n warn,\n error,\n};\n"],"mappings":"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","names":["error"]}
|
|
1
|
+
{"version":3,"sources":["../../src/config/microfrontends/utils/find-config.ts","../../src/config/microfrontends/utils/get-config-file-name.ts","../../src/config/microfrontends/utils/infer-microfrontends-location.ts","../../src/bin/logger.ts","../../src/config/errors.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\n\nexport function findConfig({\n dir,\n customConfigFilename,\n}: {\n dir: string;\n customConfigFilename: string | undefined;\n}): string | null {\n for (const filename of getPossibleConfigurationFilenames({\n customConfigFilename,\n })) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","// ordered by most likely to be the correct one\nconst DEFAULT_CONFIGURATION_FILENAMES = [\n 'microfrontends.json',\n 'microfrontends.jsonc',\n] as const;\n\nexport function getPossibleConfigurationFilenames({\n customConfigFilename,\n}: {\n // from env\n customConfigFilename: string | undefined;\n}) {\n if (customConfigFilename) {\n if (\n !customConfigFilename.endsWith('.json') &&\n !customConfigFilename.endsWith('.jsonc')\n ) {\n throw new Error(\n `Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}.` +\n ` The file name must end with '.json' or '.jsonc'.` +\n ` It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`,\n );\n }\n return Array.from(\n new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES]),\n );\n }\n return DEFAULT_CONFIGURATION_FILENAMES;\n}\n","import { readFileSync, statSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport fg from 'fast-glob';\nimport { parse } from 'jsonc-parser';\nimport { logger } from '../../../bin/logger';\nimport { MicrofrontendError } from '../../errors';\nimport type { Config } from '../../schema/types';\nimport type { ApplicationContext } from './get-application-context';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\n\n// cache the path to default configuration to avoid having to walk the file system multiple times\nconst configCache: Record<string, string> = {};\n\ninterface FindDefaultMicrofrontendPackageArgs {\n repositoryRoot: string;\n applicationContext: ApplicationContext;\n customConfigFilename: string | undefined;\n}\n\n/**\n * Given a repository root and a package name, find the path to the package.json file with the\n * given name.\n *\n * This method uses globby to find all package.json files and then reads them in parallel\n */\nfunction findPackageWithMicrofrontendsConfig({\n repositoryRoot,\n applicationContext,\n customConfigFilename,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n const applicationName = applicationContext.name;\n logger.debug(\n '[MFE Config] Searching repository for configs containing application:',\n applicationName,\n );\n\n try {\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(',')}}`,\n {\n cwd: repositoryRoot,\n absolute: true,\n onlyFiles: true,\n followSymbolicLinks: false,\n ignore: ['**/node_modules/**', '**/.git/**'],\n },\n );\n\n logger.debug(\n '[MFE Config] Found',\n microfrontendsJsonPaths.length,\n 'config file(s) in repository',\n );\n\n const matchingPaths: string[] = [];\n for (const microfrontendsJsonPath of microfrontendsJsonPaths) {\n if (\n doesApplicationExistInConfig(microfrontendsJsonPath, applicationName)\n ) {\n matchingPaths.push(microfrontendsJsonPath);\n }\n }\n\n logger.debug(\n '[MFE Config] Total matching config files:',\n matchingPaths.length,\n );\n\n if (matchingPaths.length > 1) {\n throw new MicrofrontendError(\n `Found multiple \\`microfrontends.json\\` files in the repository referencing the application \"${applicationName}\", but only one is allowed.\\n${matchingPaths.join('\\n • ')}`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n if (matchingPaths.length === 0) {\n if (\n repositoryRoot &&\n doesMisplacedConfigExist(\n repositoryRoot,\n applicationName,\n customConfigFilename,\n )\n ) {\n logger.debug(\n '[MFE Config] Found misplaced config in wrong .vercel directory in repository',\n );\n const misplacedConfigPath = join(\n repositoryRoot,\n '.vercel',\n customConfigFilename || 'microfrontends.json',\n );\n throw new MicrofrontendError(\n `Unable to automatically infer the location of the \\`microfrontends.json\\` file.\\n\\n` +\n `A microfrontends config was found in the \\`.vercel\\` directory at the repository root: ${misplacedConfigPath}\\n` +\n `However, in a monorepo, the config file should be placed in the \\`.vercel\\` directory in your application directory instead.\\n\\n` +\n `To fix this:\\n` +\n `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\\n` +\n `2. If manually defined, move the config file to the \\`.vercel\\` directory in your application\\n` +\n `3. Alternatively, set the VC_MICROFRONTENDS_CONFIG environment variable to the correct path\\n\\n` +\n `For more information, see: https://vercel.com/docs/cli/project-linking`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n let additionalErrorMessage = '';\n if (microfrontendsJsonPaths.length > 0) {\n if (!applicationContext.projectName) {\n additionalErrorMessage = `\\n\\nIf 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.`;\n } else {\n additionalErrorMessage = `\\n\\nNames of applications in \\`microfrontends.json\\` must match the Vercel Project name (${applicationContext.projectName}).`;\n }\n }\n throw new MicrofrontendError(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains the \"${applicationName}\" application.${additionalErrorMessage}\\n\\n` +\n `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.\\n\\n` +\n `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.\\n\\n` +\n `If you suspect this is thrown in error, please reach out to the Vercel team.`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n if (error instanceof MicrofrontendError) {\n throw error;\n }\n return null;\n }\n}\n\n/**\n * Given a repository root and a package name, find the path to the package directory with\n * a microfrontends config that contains the given name in its applications.\n */\nexport function inferMicrofrontendsLocation(\n opts: FindDefaultMicrofrontendPackageArgs,\n): string {\n // cache this with name to support multiple configurations in the same repository\n const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ''}`;\n\n // Check if we have a cached result\n if (configCache[cacheKey]) {\n return configCache[cacheKey];\n }\n\n const result = findPackageWithMicrofrontendsConfig(opts);\n\n if (!result) {\n throw new MicrofrontendError(\n `Could not infer the location of the \\`microfrontends.json\\` file for application \"${opts.applicationContext.name}\" starting in directory \"${opts.repositoryRoot}\".`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n // Cache the result\n configCache[cacheKey] = result;\n return result;\n}\n\nfunction existsSync(path: string): boolean {\n try {\n statSync(path);\n return true;\n } catch (_) {\n return false;\n }\n}\n\nfunction doesMisplacedConfigExist(\n repositoryRoot: string,\n applicationName: string,\n customConfigFilename: string | undefined,\n): boolean {\n logger.debug(\n '[MFE Config] Looking for misplaced config in wrong .vercel directory',\n );\n const misplacedConfigPath = join(\n repositoryRoot,\n '.vercel',\n customConfigFilename || 'microfrontends.json',\n );\n return (\n existsSync(misplacedConfigPath) &&\n doesApplicationExistInConfig(misplacedConfigPath, applicationName)\n );\n}\n\nfunction doesApplicationExistInConfig(\n microfrontendsJsonPath: string,\n applicationName: string,\n): boolean {\n try {\n const microfrontendsJsonContent = readFileSync(\n microfrontendsJsonPath,\n 'utf-8',\n );\n const microfrontendsJson = parse(microfrontendsJsonContent) as Config;\n\n if (microfrontendsJson.applications[applicationName]) {\n logger.debug(\n '[MFE Config] Found application in config:',\n microfrontendsJsonPath,\n );\n return true;\n }\n\n for (const [_, app] of Object.entries(microfrontendsJson.applications)) {\n if (app.packageName === applicationName) {\n logger.debug(\n '[MFE Config] Found application via packageName in config:',\n microfrontendsJsonPath,\n );\n return true;\n }\n }\n } catch (error) {\n logger.debug('[MFE Config] Error checking application in config:', error);\n // malformed json most likely, skip this file\n }\n return false;\n}\n","/* eslint-disable no-console */\n\nfunction debug(...args: unknown[]): void {\n if (process.env.MFE_DEBUG) {\n console.log(...args);\n }\n}\n\nfunction info(...args: unknown[]): void {\n console.log(...args);\n}\n\nfunction warn(...args: unknown[]): void {\n console.warn(...args);\n}\n\nfunction error(...args: unknown[]): void {\n console.error(...args);\n}\n\nexport const logger = {\n debug,\n info,\n warn,\n error,\n};\n","export type MicrofrontendErrorType =\n | 'config'\n | 'packageJson'\n | 'vercelJson'\n | 'application'\n | 'unknown';\n\nexport type MicrofrontendErrorSubtype =\n | 'not_found'\n | 'inference_failed'\n | 'not_found_in_env'\n | 'invalid_asset_prefix'\n | 'invalid_main_path'\n | 'does_not_match_schema'\n | 'unable_to_read_file'\n | 'unsupported_validation_env'\n | 'unsupported_version'\n | 'invalid_path'\n | 'invalid_permissions'\n | 'invalid_syntax'\n | 'missing_microfrontend_config_path'\n | 'unsupported_operation';\n\n// A mapping of error types to their subtypes.\ninterface TypeToSubtype {\n application:\n | 'invalid_asset_prefix'\n | 'invalid_path'\n | 'multiple_package_managers'\n | 'not_found';\n config:\n | 'conflicting_paths'\n | 'depcrecated_field'\n | 'does_not_match_schema'\n | 'invalid_main_path'\n | 'invalid_preview_deployment_suffix'\n | 'multiple_default_applications'\n | 'no_default_application'\n | 'not_found_in_env'\n | 'not_found'\n | 'inference_failed'\n | 'unable_to_read_file'\n | 'invalid_syntax'\n | 'invalid_permissions'\n | 'unsupported_operation'\n | 'unsupported_validation_env'\n | 'unsupported_version';\n packageJson:\n | 'missing_field_name'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n vercelJson:\n | 'missing_field_microfrontend_config_path'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n unknown: never;\n}\n\nexport type MicrofrontendErrorSource =\n | '@vercel/microfrontends'\n | '@vercel/microfrontends/next'\n | 'fs'\n | 'ajv';\n\nexport interface MicrofrontendErrorOptions<T extends MicrofrontendErrorType> {\n cause?: unknown;\n source?: MicrofrontendErrorSource;\n type?: T;\n subtype?: TypeToSubtype[T];\n}\n\ninterface HandleOptions {\n fileName?: string;\n}\n\nexport class MicrofrontendError<\n T extends MicrofrontendErrorType = 'unknown',\n> extends Error {\n public source: MicrofrontendErrorSource;\n public type: T;\n public subtype?: TypeToSubtype[T];\n\n constructor(message: string, opts?: MicrofrontendErrorOptions<T>) {\n super(message, { cause: opts?.cause });\n this.name = 'MicrofrontendsError';\n this.source = opts?.source ?? '@vercel/microfrontends';\n this.type = opts?.type ?? ('unknown' as T);\n this.subtype = opts?.subtype;\n Error.captureStackTrace(this, MicrofrontendError);\n }\n\n isKnown(): boolean {\n return this.type !== 'unknown';\n }\n\n isUnknown(): boolean {\n return !this.isKnown();\n }\n\n /**\n * Converts an error to a MicrofrontendsError.\n * @param original - The original error to convert.\n * @returns The converted MicrofrontendsError.\n */\n static convert(\n original: Error,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (opts?.fileName) {\n const err = MicrofrontendError.convertFSError(original, opts.fileName);\n if (err) {\n return err;\n }\n }\n\n if (\n original.message.includes(\n 'Code generation from strings disallowed for this context',\n )\n ) {\n return new MicrofrontendError(original.message, {\n type: 'config',\n subtype: 'unsupported_validation_env',\n source: 'ajv',\n });\n }\n\n // unknown catch-all\n return new MicrofrontendError(original.message);\n }\n\n static convertFSError(\n original: Error,\n fileName: string,\n ): MicrofrontendError<MicrofrontendErrorType> | null {\n if (original instanceof Error && 'code' in original) {\n if (original.code === 'ENOENT') {\n return new MicrofrontendError(`Could not find \"${fileName}\"`, {\n type: 'config',\n subtype: 'unable_to_read_file',\n source: 'fs',\n });\n }\n if (original.code === 'EACCES') {\n return new MicrofrontendError(\n `Permission denied while accessing \"${fileName}\"`,\n {\n type: 'config',\n subtype: 'invalid_permissions',\n source: 'fs',\n },\n );\n }\n }\n\n if (original instanceof SyntaxError) {\n return new MicrofrontendError(\n `Failed to parse \"${fileName}\": Invalid JSON format.`,\n {\n type: 'config',\n subtype: 'invalid_syntax',\n source: 'fs',\n },\n );\n }\n\n return null;\n }\n\n /**\n * Handles an unknown error and returns a MicrofrontendsError instance.\n * @param err - The error to handle.\n * @returns A MicrofrontendsError instance.\n */\n static handle(\n err: unknown,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (err instanceof MicrofrontendError) {\n return err as MicrofrontendError<MicrofrontendErrorType>;\n }\n\n // handle Error instances\n if (err instanceof Error) {\n return MicrofrontendError.convert(err, opts);\n }\n\n // handle object errors\n if (typeof err === 'object' && err !== null) {\n if ('message' in err && typeof err.message === 'string') {\n return MicrofrontendError.convert(new Error(err.message), opts);\n }\n }\n\n return new MicrofrontendError('An unknown error occurred');\n }\n}\n"],"mappings":"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","names":["join","join","error"]}
|
package/dist/next/client.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
"use strict";var I=Object.create;var C=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var
|
|
2
|
+
"use strict";var I=Object.create;var C=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var J=Object.getPrototypeOf,B=Object.prototype.hasOwnProperty;var V=(t,e)=>{for(var n in e)C(t,n,{get:e[n],enumerable:!0})},v=(t,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of D(e))!B.call(t,o)&&o!==n&&C(t,o,{get:()=>e[o],enumerable:!(i=z(e,o))||i.enumerable});return t};var _=(t,e,n)=>(n=t!=null?I(J(t)):{},v(e||!t||!t.__esModule?C(n,"default",{value:t,enumerable:!0}):n,t)),U=t=>v(C({},"__esModule",{value:!0}),t);var K={};V(K,{Link:()=>A,PrefetchCrossZoneLinks:()=>q,PrefetchCrossZoneLinksContext:()=>P,PrefetchCrossZoneLinksProvider:()=>G,useZoneForHref:()=>T});module.exports=U(K);var H=_(require("next/link.js"),1),g=require("react");var h=require("react");var N=require("path-to-regexp"),R=new Map,W=t=>{let e=R.get(t);if(e)return e;let n=(0,N.pathToRegexp)(t);return R.set(t,n),n},u=class{constructor(e,n){this.pathCache={};this.hasFlaggedPaths=e.hasFlaggedPaths??!1;for(let i of Object.values(e.applications))if(i.routing){i.routing.some(r=>r.flag)&&(this.hasFlaggedPaths=!0);let o=[],s=[];for(let r of i.routing)if(r.flag){if(n?.removeFlaggedPaths)continue;r.group&&delete r.group,o.push(r)}else s.push(...r.paths);s.length>0&&o.push({paths:s}),i.routing=o}this.serialized=e,this.hasFlaggedPaths&&(this.serialized.hasFlaggedPaths=this.hasFlaggedPaths),this.applications=e.applications}static fromEnv(e){if(!e)throw new Error("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");return new u(JSON.parse(e))}isEqual(e){return this===e||JSON.stringify(this.applications)===JSON.stringify(e.applications)}getApplicationNameForPath(e){if(!e.startsWith("/"))throw new Error("Path must start with a /");if(this.pathCache[e])return this.pathCache[e];let n=new URL(e,"https://example.com").pathname;for(let[o,s]of Object.entries(this.applications))if(s.routing){for(let r of s.routing)for(let a of r.paths)if(W(a).test(n))return this.pathCache[e]=o,o}let i=Object.entries(this.applications).find(([,o])=>o.default);return i?(this.pathCache[e]=i[0],i[0]):null}serialize(){return this.serialized}};var S=new Map,b=new Map,k=t=>{let e=S.get(t||"");if(e)return e;let n=u.fromEnv(t);return S.set(t||"",n),n},E=null,L=null;async function X(){try{let t=await fetch("/.well-known/vercel/microfrontends/client-config");if(t.status!==200)return null;let e=await t.json(),n=new u(e.config);return L=n,n}catch{return null}}function m(t){let[e,n]=(0,h.useState)(()=>L??k(t)),i=(0,h.useMemo)(()=>{if(process.env.NODE_ENV==="test"&&process.env.MFE_FORCE_CLIENT_CONFIG_FROM_SERVER!=="1"||L)return!1;let r=b.get(t||"");if(r!==void 0)return r;let f=k(t).hasFlaggedPaths;return b.set(t||"",f),!!f},[t]),[o,s]=(0,h.useState)(i);return(0,h.useEffect)(()=>{i&&(E||(E=X()),E.then(r=>{r&&n(a=>a.isEqual(r)?a:r)}).finally(()=>{s(!1)}))},[i]),{clientConfig:e,isLoading:o}}var O=_(require("next/script.js"),1),d=require("react");var w=require("react/jsx-runtime"),y="data-prefetch",l={anyZone:"[data-zone]",external:'[data-zone="null"]',sameZone:'[data-zone="same"]',prefetch:`[${y}]`},M={and:[{href_matches:"/*"},{selector_matches:l.anyZone},{not:{selector_matches:l.sameZone}},{not:{selector_matches:l.external}}]},$={and:[{href_matches:"/*"},{selector_matches:l.anyZone},{not:{selector_matches:l.sameZone}},{not:{selector_matches:l.external}},{selector_matches:l.prefetch}]};function F(t){if(!t)return!0;if("checkVisibility"in t)return t.checkVisibility({opacityProperty:!0});let e=t,n=window.getComputedStyle(e);return n.display==="none"||n.visibility==="hidden"||n.opacity==="0"?!1:F(e.parentElement)}function q({prerenderEagerness:t="conservative"}){let{isLoading:e}=m(process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG),[n,i]=(0,d.useState)([]);return(0,d.useEffect)(()=>{if(e)return;let s=new IntersectionObserver(r=>{r.forEach(a=>{a.isIntersecting&&!a.target.hasAttribute(y)&&F(a.target)&&a.target.setAttribute(y,"true")})},{root:null,rootMargin:"0px",threshold:.1});return n.forEach(r=>s.observe(r)),()=>{s.disconnect()}},[e,n]),(0,d.useEffect)(()=>{if(e)return;let s=new MutationObserver(r=>{r.some(f=>f.type==="childList"&&f.addedNodes.length>0||f.type==="attributes"&&f.attributeName==="href")&&i(Array.from(document.querySelectorAll(`a${l.anyZone}:not(${l.prefetch}):not(${l.sameZone}):not(${l.external})`)))});return s.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["href"]}),()=>{s.disconnect()}},[e]),e?null:(0,w.jsx)(O.default,{dangerouslySetInnerHTML:{__html:JSON.stringify({prefetch:[{eagerness:"moderate",where:M},{eagerness:"immediate",where:$}],prerender:[{eagerness:t,where:M}]})},id:"prefetch-zones-links",type:"speculationrules"})}var c=require("react"),p=require("react/jsx-runtime"),P=(0,c.createContext)({prefetchHref:()=>{}});function G({children:t}){let[e,n]=(0,c.useState)(new Set),i=(0,c.useRef)(typeof navigator<"u"&&(navigator.userAgent.includes("Firefox")||navigator.userAgent.includes("Safari")&&!navigator.userAgent.includes("Chrome"))),o=(0,c.useCallback)(r=>{(0,c.startTransition)(()=>{n(a=>a.has(r)?a:new Set(a).add(r))})},[]),s=(0,c.useMemo)(()=>({prefetchHref:o}),[o]);return i.current?(0,p.jsxs)(P.Provider,{value:s,children:[t,[...e].map(r=>(0,p.jsx)("link",{as:"fetch",href:r,rel:"preload"},r))]}):(0,p.jsx)(p.Fragment,{children:t})}var x=require("react/jsx-runtime"),j=process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION_HASH;function T(t){let{clientConfig:e,isLoading:n}=m(process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG),{isRelativePath:i,zoneOfHref:o}=(0,g.useMemo)(()=>{let r=typeof t=="string"&&t.startsWith("/");return{isRelativePath:r,zoneOfHref:r?e.getApplicationNameForPath(t):null}},[e,t]);return typeof t=="string"&&!t.length?{zoneOfHref:null,isDifferentZone:!1,isLoading:!1}:{zoneOfHref:o,isDifferentZone:!i||(o?j!==o:!1),isLoading:n}}var A=(0,g.forwardRef)(({children:t,...e},n)=>{let{prefetchHref:i}=(0,g.useContext)(P),{zoneOfHref:o,isDifferentZone:s,isLoading:r}=T(e.href);function a(){e.href&&i(e.href)}if(s&&o!==null){let{prefetch:f,...Z}=e;return(0,x.jsx)("a",{...Z,"data-zone":o,onFocus:e.prefetch!==!1?a:void 0,onMouseOver:e.prefetch!==!1?a:void 0,children:t})}return(0,x.jsx)(H.default,{...e,"data-zone":o?"same":"null",prefetch:e.prefetch??(r?!1:void 0),ref:n,children:t})});A.displayName="MicrofrontendsLink";0&&(module.exports={Link,PrefetchCrossZoneLinks,PrefetchCrossZoneLinksContext,PrefetchCrossZoneLinksProvider,useZoneForHref});
|
|
3
3
|
//# sourceMappingURL=client.cjs.map
|