@vercel/microfrontends 2.1.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +4 -0
  3. package/dist/bin/cli.cjs +125 -89
  4. package/dist/config.d.ts +2 -2
  5. package/dist/experimental/sveltekit.cjs +97 -62
  6. package/dist/experimental/sveltekit.cjs.map +1 -1
  7. package/dist/experimental/sveltekit.d.ts +6 -0
  8. package/dist/experimental/sveltekit.js +97 -62
  9. package/dist/experimental/sveltekit.js.map +1 -1
  10. package/dist/experimental/vite.cjs +96 -65
  11. package/dist/experimental/vite.cjs.map +1 -1
  12. package/dist/experimental/vite.js +96 -65
  13. package/dist/experimental/vite.js.map +1 -1
  14. package/dist/microfrontends/server.cjs +92 -59
  15. package/dist/microfrontends/server.cjs.map +1 -1
  16. package/dist/microfrontends/server.d.ts +2 -2
  17. package/dist/microfrontends/server.js +92 -59
  18. package/dist/microfrontends/server.js.map +1 -1
  19. package/dist/microfrontends/utils.cjs +3 -3
  20. package/dist/microfrontends/utils.cjs.map +1 -1
  21. package/dist/microfrontends/utils.d.ts +1 -1
  22. package/dist/microfrontends/utils.js +3 -3
  23. package/dist/microfrontends/utils.js.map +1 -1
  24. package/dist/next/config.cjs +133 -115
  25. package/dist/next/config.cjs.map +1 -1
  26. package/dist/next/config.d.ts +11 -1
  27. package/dist/next/config.js +133 -115
  28. package/dist/next/config.js.map +1 -1
  29. package/dist/next/middleware.cjs +35 -17
  30. package/dist/next/middleware.cjs.map +1 -1
  31. package/dist/next/middleware.js +35 -17
  32. package/dist/next/middleware.js.map +1 -1
  33. package/dist/next/testing.d.ts +2 -2
  34. package/dist/overrides.d.ts +3 -3
  35. package/dist/schema.d.ts +2 -2
  36. package/dist/{types-88602303.d.ts → types-b9ea41b2.d.ts} +1 -1
  37. package/dist/{types-e7523e61.d.ts → types-dcd8b17a.d.ts} +71 -24
  38. package/dist/utils/mfe-port.cjs +92 -59
  39. package/dist/utils/mfe-port.cjs.map +1 -1
  40. package/dist/utils/mfe-port.js +92 -59
  41. package/dist/utils/mfe-port.js.map +1 -1
  42. package/dist/validation.cjs +47 -38
  43. package/dist/validation.cjs.map +1 -1
  44. package/dist/validation.d.ts +1 -1
  45. package/dist/validation.js +47 -38
  46. package/dist/validation.js.map +1 -1
  47. package/package.json +1 -1
  48. package/schema/schema.json +47 -38
@@ -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","const DEFAULT_CONFIGURATION_FILENAMES = [\n 'microfrontends.jsonc',\n 'microfrontends.json',\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 `The VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable must end with '.json' or '.jsonc'. Received: ${customConfigFilename}`,\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/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"]}
@@ -18,6 +18,6 @@ declare function inferMicrofrontendsLocation(opts: FindDefaultMicrofrontendPacka
18
18
 
19
19
  declare function getPossibleConfigurationFilenames({ customConfigFilename, }: {
20
20
  customConfigFilename: string | undefined;
21
- }): string[] | readonly ["microfrontends.jsonc", "microfrontends.json"];
21
+ }): string[] | readonly ["microfrontends.json", "microfrontends.jsonc"];
22
22
 
23
23
  export { findConfig, getPossibleConfigurationFilenames, inferMicrofrontendsLocation };
@@ -4,8 +4,8 @@ import { join } from "node:path";
4
4
 
5
5
  // src/config/microfrontends/utils/get-config-file-name.ts
6
6
  var DEFAULT_CONFIGURATION_FILENAMES = [
7
- "microfrontends.jsonc",
8
- "microfrontends.json"
7
+ "microfrontends.json",
8
+ "microfrontends.jsonc"
9
9
  ];
10
10
  function getPossibleConfigurationFilenames({
11
11
  customConfigFilename
@@ -13,7 +13,7 @@ function getPossibleConfigurationFilenames({
13
13
  if (customConfigFilename) {
14
14
  if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
15
15
  throw new Error(
16
- `The VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable must end with '.json' or '.jsonc'. Received: ${customConfigFilename}`
16
+ `Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}. The file name must end with '.json' or '.jsonc'. It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`
17
17
  );
18
18
  }
19
19
  return Array.from(
@@ -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","const DEFAULT_CONFIGURATION_FILENAMES = [\n 'microfrontends.jsonc',\n 'microfrontends.json',\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 `The VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable must end with '.json' or '.jsonc'. Received: ${customConfigFilename}`,\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":[]}
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":"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","names":[]}