@vercel/microfrontends 2.2.0 → 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.
Files changed (59) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/cli/index.cjs +0 -1
  3. package/dist/bin/cli.cjs +551 -381
  4. package/dist/config.cjs +191 -169
  5. package/dist/config.cjs.map +1 -1
  6. package/dist/config.d.ts +3 -2
  7. package/dist/config.js +192 -170
  8. package/dist/config.js.map +1 -1
  9. package/dist/experimental/sveltekit.cjs +643 -489
  10. package/dist/experimental/sveltekit.cjs.map +1 -1
  11. package/dist/experimental/sveltekit.js +645 -491
  12. package/dist/experimental/sveltekit.js.map +1 -1
  13. package/dist/experimental/vite.cjs +671 -519
  14. package/dist/experimental/vite.cjs.map +1 -1
  15. package/dist/experimental/vite.js +669 -517
  16. package/dist/experimental/vite.js.map +1 -1
  17. package/dist/microfrontends/server.cjs +661 -509
  18. package/dist/microfrontends/server.cjs.map +1 -1
  19. package/dist/microfrontends/server.d.ts +2 -2
  20. package/dist/microfrontends/server.js +663 -511
  21. package/dist/microfrontends/server.js.map +1 -1
  22. package/dist/microfrontends/utils.cjs +117 -23
  23. package/dist/microfrontends/utils.cjs.map +1 -1
  24. package/dist/microfrontends/utils.d.ts +4 -4
  25. package/dist/microfrontends/utils.js +118 -24
  26. package/dist/microfrontends/utils.js.map +1 -1
  27. package/dist/next/client.cjs +1 -1
  28. package/dist/next/client.cjs.map +1 -1
  29. package/dist/next/client.d.ts +8 -8
  30. package/dist/next/client.js +1 -1
  31. package/dist/next/client.js.map +1 -1
  32. package/dist/next/config.cjs +784 -626
  33. package/dist/next/config.cjs.map +1 -1
  34. package/dist/next/config.js +782 -624
  35. package/dist/next/config.js.map +1 -1
  36. package/dist/next/middleware.cjs +244 -222
  37. package/dist/next/middleware.cjs.map +1 -1
  38. package/dist/next/middleware.js +245 -223
  39. package/dist/next/middleware.js.map +1 -1
  40. package/dist/next/testing.cjs +192 -170
  41. package/dist/next/testing.cjs.map +1 -1
  42. package/dist/next/testing.d.ts +1 -1
  43. package/dist/next/testing.js +193 -171
  44. package/dist/next/testing.js.map +1 -1
  45. package/dist/overrides.cjs +5 -5
  46. package/dist/overrides.cjs.map +1 -1
  47. package/dist/overrides.d.ts +9 -9
  48. package/dist/overrides.js +5 -5
  49. package/dist/overrides.js.map +1 -1
  50. package/dist/utils/mfe-port.cjs +689 -522
  51. package/dist/utils/mfe-port.cjs.map +1 -1
  52. package/dist/utils/mfe-port.d.ts +9 -1
  53. package/dist/utils/mfe-port.js +687 -521
  54. package/dist/utils/mfe-port.js.map +1 -1
  55. package/dist/validation.cjs +8 -24
  56. package/dist/validation.cjs.map +1 -1
  57. package/dist/validation.js +8 -24
  58. package/dist/validation.js.map +1 -1
  59. 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 import_jsonc_parser = require("jsonc-parser");
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 {
@@ -183,6 +205,10 @@ function findPackageWithMicrofrontendsConfig({
183
205
  customConfigFilename
184
206
  }) {
185
207
  const applicationName = applicationContext.name;
208
+ logger.debug(
209
+ "[MFE Config] Searching repository for configs containing application:",
210
+ applicationName
211
+ );
186
212
  try {
187
213
  const microfrontendsJsonPaths = import_fast_glob.default.globSync(
188
214
  `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
@@ -194,28 +220,21 @@ function findPackageWithMicrofrontendsConfig({
194
220
  ignore: ["**/node_modules/**", "**/.git/**"]
195
221
  }
196
222
  );
223
+ logger.debug(
224
+ "[MFE Config] Found",
225
+ microfrontendsJsonPaths.length,
226
+ "config file(s) in repository"
227
+ );
197
228
  const matchingPaths = [];
198
229
  for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
199
- try {
200
- const microfrontendsJsonContent = (0, import_node_fs2.readFileSync)(
201
- microfrontendsJsonPath,
202
- "utf-8"
203
- );
204
- const microfrontendsJson = (0, import_jsonc_parser.parse)(microfrontendsJsonContent);
205
- if (microfrontendsJson.applications[applicationName]) {
206
- matchingPaths.push(microfrontendsJsonPath);
207
- } else {
208
- for (const [_, app] of Object.entries(
209
- microfrontendsJson.applications
210
- )) {
211
- if (app.packageName === applicationName) {
212
- matchingPaths.push(microfrontendsJsonPath);
213
- }
214
- }
215
- }
216
- } catch (error) {
230
+ if (doesApplicationExistInConfig(microfrontendsJsonPath, applicationName)) {
231
+ matchingPaths.push(microfrontendsJsonPath);
217
232
  }
218
233
  }
234
+ logger.debug(
235
+ "[MFE Config] Total matching config files:",
236
+ matchingPaths.length
237
+ );
219
238
  if (matchingPaths.length > 1) {
220
239
  throw new MicrofrontendError(
221
240
  `Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
@@ -224,6 +243,34 @@ ${matchingPaths.join("\n \u2022 ")}`,
224
243
  );
225
244
  }
226
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
+ }
227
274
  let additionalErrorMessage = "";
228
275
  if (microfrontendsJsonPaths.length > 0) {
229
276
  if (!applicationContext.projectName) {
@@ -249,9 +296,9 @@ If you suspect this is thrown in error, please reach out to the Vercel team.`,
249
296
  }
250
297
  const [packageJsonPath] = matchingPaths;
251
298
  return (0, import_node_path2.dirname)(packageJsonPath);
252
- } catch (error) {
253
- if (error instanceof MicrofrontendError) {
254
- throw error;
299
+ } catch (error2) {
300
+ if (error2 instanceof MicrofrontendError) {
301
+ throw error2;
255
302
  }
256
303
  return null;
257
304
  }
@@ -271,6 +318,53 @@ function inferMicrofrontendsLocation(opts) {
271
318
  configCache[cacheKey] = result;
272
319
  return result;
273
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
+ }
274
368
  // Annotate the CommonJS export names for ESM import in node:
275
369
  0 && (module.exports = {
276
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"],"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 { 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 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 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 matchingPaths.push(microfrontendsJsonPath);\n } else {\n for (const [_, app] of Object.entries(\n microfrontendsJson.applications,\n )) {\n if (app.packageName === applicationName) {\n matchingPaths.push(microfrontendsJsonPath);\n }\n }\n }\n } catch (error) {\n // malformed json most likely, skip this file\n }\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"],"mappings":"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","names":["fs","import_node_path","import_node_fs","fg"]}
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 { dirname } from "node:path";
44
- import { readFileSync } from "node:fs";
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 {
@@ -145,6 +167,10 @@ function findPackageWithMicrofrontendsConfig({
145
167
  customConfigFilename
146
168
  }) {
147
169
  const applicationName = applicationContext.name;
170
+ logger.debug(
171
+ "[MFE Config] Searching repository for configs containing application:",
172
+ applicationName
173
+ );
148
174
  try {
149
175
  const microfrontendsJsonPaths = fg.globSync(
150
176
  `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
@@ -156,28 +182,21 @@ function findPackageWithMicrofrontendsConfig({
156
182
  ignore: ["**/node_modules/**", "**/.git/**"]
157
183
  }
158
184
  );
185
+ logger.debug(
186
+ "[MFE Config] Found",
187
+ microfrontendsJsonPaths.length,
188
+ "config file(s) in repository"
189
+ );
159
190
  const matchingPaths = [];
160
191
  for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
161
- try {
162
- const microfrontendsJsonContent = readFileSync(
163
- microfrontendsJsonPath,
164
- "utf-8"
165
- );
166
- const microfrontendsJson = parse(microfrontendsJsonContent);
167
- if (microfrontendsJson.applications[applicationName]) {
168
- matchingPaths.push(microfrontendsJsonPath);
169
- } else {
170
- for (const [_, app] of Object.entries(
171
- microfrontendsJson.applications
172
- )) {
173
- if (app.packageName === applicationName) {
174
- matchingPaths.push(microfrontendsJsonPath);
175
- }
176
- }
177
- }
178
- } catch (error) {
192
+ if (doesApplicationExistInConfig(microfrontendsJsonPath, applicationName)) {
193
+ matchingPaths.push(microfrontendsJsonPath);
179
194
  }
180
195
  }
196
+ logger.debug(
197
+ "[MFE Config] Total matching config files:",
198
+ matchingPaths.length
199
+ );
181
200
  if (matchingPaths.length > 1) {
182
201
  throw new MicrofrontendError(
183
202
  `Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
@@ -186,6 +205,34 @@ ${matchingPaths.join("\n \u2022 ")}`,
186
205
  );
187
206
  }
188
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
+ }
189
236
  let additionalErrorMessage = "";
190
237
  if (microfrontendsJsonPaths.length > 0) {
191
238
  if (!applicationContext.projectName) {
@@ -211,9 +258,9 @@ If you suspect this is thrown in error, please reach out to the Vercel team.`,
211
258
  }
212
259
  const [packageJsonPath] = matchingPaths;
213
260
  return dirname(packageJsonPath);
214
- } catch (error) {
215
- if (error instanceof MicrofrontendError) {
216
- throw error;
261
+ } catch (error2) {
262
+ if (error2 instanceof MicrofrontendError) {
263
+ throw error2;
217
264
  }
218
265
  return null;
219
266
  }
@@ -233,6 +280,53 @@ function inferMicrofrontendsLocation(opts) {
233
280
  configCache[cacheKey] = result;
234
281
  return result;
235
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
+ }
236
330
  export {
237
331
  findConfig,
238
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"],"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 { 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 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 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 matchingPaths.push(microfrontendsJsonPath);\n } else {\n for (const [_, app] of Object.entries(\n microfrontendsJson.applications,\n )) {\n if (app.packageName === applicationName) {\n matchingPaths.push(microfrontendsJsonPath);\n }\n }\n }\n } catch (error) {\n // malformed json most likely, skip this file\n }\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"],"mappings":";AAAA,OAAO,QAAQ;AACf,SAAS,YAAY;;;ACArB,IAAM,kCAAkC;AAAA,EACtC;AAAA,EACA;AACF;AAEO,SAAS,kCAAkC;AAAA,EAChD;AACF,GAGG;AACD,MAAI,sBAAsB;AACxB,QACE,CAAC,qBAAqB,SAAS,OAAO,KACtC,CAAC,qBAAqB,SAAS,QAAQ,GACvC;AACA,YAAM,IAAI;AAAA,QACR,+EAA+E;AAAA,MAGjF;AAAA,IACF;AACA,WAAO,MAAM;AAAA,MACX,oBAAI,IAAI,CAAC,sBAAsB,GAAG,+BAA+B,CAAC;AAAA,IACpE;AAAA,EACF;AACA,SAAO;AACT;;;ADxBO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AACF,GAGkB;AAChB,aAAW,YAAY,kCAAkC;AAAA,IACvD;AAAA,EACF,CAAC,GAAG;AACF,UAAM,cAAc,KAAK,KAAK,QAAQ;AACtC,QAAI,GAAG,WAAW,WAAW,GAAG;AAC9B,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;;AErBA,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAC7B,SAAS,aAAa;AACtB,OAAO,QAAQ;;;AC0ER,IAAM,qBAAN,cAEG,MAAM;AAAA,EAKd,YAAY,SAAiB,MAAqC;AAChE,UAAM,SAAS,EAAE,OAAO,MAAM,MAAM,CAAC;AACrC,SAAK,OAAO;AACZ,SAAK,SAAS,MAAM,UAAU;AAC9B,SAAK,OAAO,MAAM,QAAS;AAC3B,SAAK,UAAU,MAAM;AACrB,UAAM,kBAAkB,MAAM,kBAAkB;AAAA,EAClD;AAAA,EAEA,UAAmB;AACjB,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA,EAEA,YAAqB;AACnB,WAAO,CAAC,KAAK,QAAQ;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,QACL,UACA,MAC4C;AAC5C,QAAI,MAAM,UAAU;AAClB,YAAM,MAAM,mBAAmB,eAAe,UAAU,KAAK,QAAQ;AACrE,UAAI,KAAK;AACP,eAAO;AAAA,MACT;AAAA,IACF;AAEA,QACE,SAAS,QAAQ;AAAA,MACf;AAAA,IACF,GACA;AACA,aAAO,IAAI,mBAAmB,SAAS,SAAS;AAAA,QAC9C,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAGA,WAAO,IAAI,mBAAmB,SAAS,OAAO;AAAA,EAChD;AAAA,EAEA,OAAO,eACL,UACA,UACmD;AACnD,QAAI,oBAAoB,SAAS,UAAU,UAAU;AACnD,UAAI,SAAS,SAAS,UAAU;AAC9B,eAAO,IAAI,mBAAmB,mBAAmB,aAAa;AAAA,UAC5D,MAAM;AAAA,UACN,SAAS;AAAA,UACT,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AACA,UAAI,SAAS,SAAS,UAAU;AAC9B,eAAO,IAAI;AAAA,UACT,sCAAsC;AAAA,UACtC;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA,YACT,QAAQ;AAAA,UACV;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,oBAAoB,aAAa;AACnC,aAAO,IAAI;AAAA,QACT,oBAAoB;AAAA,QACpB;AAAA,UACE,MAAM;AAAA,UACN,SAAS;AAAA,UACT,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,OACL,KACA,MAC4C;AAC5C,QAAI,eAAe,oBAAoB;AACrC,aAAO;AAAA,IACT;AAGA,QAAI,eAAe,OAAO;AACxB,aAAO,mBAAmB,QAAQ,KAAK,IAAI;AAAA,IAC7C;AAGA,QAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAI,aAAa,OAAO,OAAO,IAAI,YAAY,UAAU;AACvD,eAAO,mBAAmB,QAAQ,IAAI,MAAM,IAAI,OAAO,GAAG,IAAI;AAAA,MAChE;AAAA,IACF;AAEA,WAAO,IAAI,mBAAmB,2BAA2B;AAAA,EAC3D;AACF;;;AD5LA,IAAM,cAAsC,CAAC;AAc7C,SAAS,oCAAoC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AACF,GAAuD;AACrD,QAAM,kBAAkB,mBAAmB;AAC3C,MAAI;AAEF,UAAM,0BAA0B,GAAG;AAAA,MACjC,OAAO,kCAAkC,EAAE,qBAAqB,CAAC,EAAE,KAAK,GAAG;AAAA,MAC3E;AAAA,QACE,KAAK;AAAA,QACL,UAAU;AAAA,QACV,WAAW;AAAA,QACX,qBAAqB;AAAA,QACrB,QAAQ,CAAC,sBAAsB,YAAY;AAAA,MAC7C;AAAA,IACF;AAEA,UAAM,gBAA0B,CAAC;AACjC,eAAW,0BAA0B,yBAAyB;AAC5D,UAAI;AACF,cAAM,4BAA4B;AAAA,UAChC;AAAA,UACA;AAAA,QACF;AACA,cAAM,qBAAqB,MAAM,yBAAyB;AAE1D,YAAI,mBAAmB,aAAa,eAAe,GAAG;AACpD,wBAAc,KAAK,sBAAsB;AAAA,QAC3C,OAAO;AACL,qBAAW,CAAC,GAAG,GAAG,KAAK,OAAO;AAAA,YAC5B,mBAAmB;AAAA,UACrB,GAAG;AACD,gBAAI,IAAI,gBAAgB,iBAAiB;AACvC,4BAAc,KAAK,sBAAsB;AAAA,YAC3C;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,OAAP;AAAA,MAEF;AAAA,IACF;AAEA,QAAI,cAAc,SAAS,GAAG;AAC5B,YAAM,IAAI;AAAA,QACR,+FAA+F;AAAA,EAA+C,cAAc,KAAK,aAAQ;AAAA,QACzK,EAAE,MAAM,UAAU,SAAS,mBAAmB;AAAA,MAChD;AAAA,IACF;AAEA,QAAI,cAAc,WAAW,GAAG;AAC9B,UAAI,yBAAyB;AAC7B,UAAI,wBAAwB,SAAS,GAAG;AACtC,YAAI,CAAC,mBAAmB,aAAa;AACnC,mCAAyB;AAAA;AAAA,+BAAoC,mBAAmB;AAAA,QAClF,OAAO;AACL,mCAAyB;AAAA;AAAA,uFAA4F,mBAAmB;AAAA,QAC1I;AAAA,MACF;AACA,YAAM,IAAI;AAAA,QACR,sFAAsF,gCAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAItH,EAAE,MAAM,UAAU,SAAS,mBAAmB;AAAA,MAChD;AAAA,IACF;AAEA,UAAM,CAAC,eAAe,IAAI;AAC1B,WAAO,QAAQ,eAAe;AAAA,EAChC,SAAS,OAAP;AACA,QAAI,iBAAiB,oBAAoB;AACvC,YAAM;AAAA,IACR;AACA,WAAO;AAAA,EACT;AACF;AAMO,SAAS,4BACd,MACQ;AAER,QAAM,WAAW,GAAG,KAAK,kBAAkB,KAAK,mBAAmB,OAAO,KAAK,uBAAuB,IAAI,KAAK,yBAAyB;AAGxI,MAAI,YAAY,QAAQ,GAAG;AACzB,WAAO,YAAY,QAAQ;AAAA,EAC7B;AAEA,QAAM,SAAS,oCAAoC,IAAI;AAEvD,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR,qFAAqF,KAAK,mBAAmB,gCAAgC,KAAK;AAAA,MAClJ,EAAE,MAAM,UAAU,SAAS,mBAAmB;AAAA,IAChD;AAAA,EACF;AAGA,cAAY,QAAQ,IAAI;AACxB,SAAO;AACT;","names":[]}
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"]}
@@ -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 B=Object.getPrototypeOf,J=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))!J.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(B(t)):{},v(e||!t||!t.__esModule?C(n,"default",{value:t,enumerable:!0}):n,t)),U=t=>v(C({},"__esModule",{value:!0}),t);var j={};V(j,{Link:()=>H,PrefetchCrossZoneLinks:()=>G,PrefetchCrossZoneLinksContext:()=>P,PrefetchCrossZoneLinksProvider:()=>$,useZoneForHref:()=>A});module.exports=U(j);var d=require("react"),T=_(require("next/link.js"),1);var h=require("react");var k=require("path-to-regexp"),R=new Map,W=t=>{let e=R.get(t);if(e)return e;let n=(0,k.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 N=new Map,b=new Map,M=t=>{let e=N.get(t||"");if(e)return e;let n=u.fromEnv(t);return N.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??M(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=M(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)}))},[t,e.applications,i]),{clientConfig:e,isLoading:o}}var c=require("react"),p=require("react/jsx-runtime"),P=(0,c.createContext)({prefetchHref:()=>{}});function $({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 g=require("react"),F=_(require("next/script.js"),1);var w=require("react/jsx-runtime"),x="data-prefetch",l={anyZone:"[data-zone]",external:'[data-zone="null"]',sameZone:'[data-zone="same"]',prefetch:`[${x}]`},S={and:[{href_matches:"/*"},{selector_matches:l.anyZone},{not:{selector_matches:l.sameZone}},{not:{selector_matches:l.external}}]},q={and:[{href_matches:"/*"},{selector_matches:l.anyZone},{not:{selector_matches:l.sameZone}},{not:{selector_matches:l.external}},{selector_matches:l.prefetch}]};function O(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:O(e.parentElement)}function G({prerenderEagerness:t="conservative"}){let{isLoading:e}=m(process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG),[n,i]=(0,g.useState)([]);return(0,g.useEffect)(()=>{if(e)return;let s=new IntersectionObserver(r=>{r.forEach(a=>{a.isIntersecting&&!a.target.hasAttribute(x)&&O(a.target)&&a.target.setAttribute(x,"true")})},{root:null,rootMargin:"0px",threshold:.1});return n.forEach(r=>s.observe(r)),()=>{s.disconnect()}},[e,n]),(0,g.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)(F.default,{dangerouslySetInnerHTML:{__html:JSON.stringify({prefetch:[{eagerness:"moderate",where:S},{eagerness:"immediate",where:q}],prerender:[{eagerness:t,where:S}]})},id:"prefetch-zones-links",type:"speculationrules"})}var y=require("react/jsx-runtime"),K=process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION_HASH;function A(t){let{clientConfig:e,isLoading:n}=m(process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG),{isRelativePath:i,zoneOfHref:o}=(0,d.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?K!==o:!1),isLoading:n}}var H=(0,d.forwardRef)(({children:t,...e},n)=>{let{prefetchHref:i}=(0,d.useContext)(P),{zoneOfHref:o,isDifferentZone:s,isLoading:r}=A(e.href);function a(){e.href&&i(e.href)}if(s&&o!==null){let{prefetch:f,...Z}=e;return(0,y.jsx)("a",{...Z,"data-zone":o,onFocus:e.prefetch!==!1?a:void 0,onMouseOver:e.prefetch!==!1?a:void 0,children:t})}return(0,y.jsx)(T.default,{...e,"data-zone":o?"same":"null",prefetch:e.prefetch??(r?!1:void 0),ref:n,children:t})});H.displayName="MicrofrontendsLink";0&&(module.exports={Link,PrefetchCrossZoneLinks,PrefetchCrossZoneLinksContext,PrefetchCrossZoneLinksProvider,useZoneForHref});
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