@vercel/microfrontends 2.0.0 → 2.1.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.
- package/CHANGELOG.md +17 -0
- package/README.md +1 -5
- package/dist/bin/cli.cjs +226 -79
- package/dist/config.cjs +5 -4
- package/dist/config.cjs.map +1 -1
- package/dist/config.js +5 -4
- package/dist/config.js.map +1 -1
- package/dist/experimental/sveltekit.cjs +51 -20
- package/dist/experimental/sveltekit.cjs.map +1 -1
- package/dist/experimental/sveltekit.js +51 -20
- package/dist/experimental/sveltekit.js.map +1 -1
- package/dist/experimental/vite.cjs +51 -20
- package/dist/experimental/vite.cjs.map +1 -1
- package/dist/experimental/vite.js +51 -20
- package/dist/experimental/vite.js.map +1 -1
- package/dist/microfrontends/server.cjs +51 -20
- package/dist/microfrontends/server.cjs.map +1 -1
- package/dist/microfrontends/server.js +51 -20
- package/dist/microfrontends/server.js.map +1 -1
- package/dist/microfrontends/utils.cjs +32 -7
- package/dist/microfrontends/utils.cjs.map +1 -1
- package/dist/microfrontends/utils.d.ts +8 -2
- package/dist/microfrontends/utils.js +31 -7
- package/dist/microfrontends/utils.js.map +1 -1
- package/dist/next/client.cjs +1 -1
- package/dist/next/client.cjs.map +1 -1
- package/dist/next/client.d.ts +15 -1
- package/dist/next/client.js +1 -1
- package/dist/next/client.js.map +1 -1
- package/dist/next/config.cjs +62 -20
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.js +62 -20
- package/dist/next/config.js.map +1 -1
- package/dist/next/middleware.cjs +5 -4
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.js +5 -4
- package/dist/next/middleware.js.map +1 -1
- package/dist/next/testing.cjs +5 -4
- package/dist/next/testing.cjs.map +1 -1
- package/dist/next/testing.js +5 -4
- package/dist/next/testing.js.map +1 -1
- package/dist/utils/mfe-port.cjs +66 -40
- package/dist/utils/mfe-port.cjs.map +1 -1
- package/dist/utils/mfe-port.js +66 -40
- package/dist/utils/mfe-port.js.map +1 -1
- package/package.json +4 -4
package/dist/next/testing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/next/testing/index.ts","../../src/config/microfrontends-config/isomorphic/index.ts","../../src/config/errors.ts","../../src/config/microfrontends-config/utils/get-config-from-env.ts","../../src/config/schema/utils/is-default-app.ts","../../src/config/overrides/constants.ts","../../src/config/overrides/is-override-cookie.ts","../../src/config/overrides/get-override-from-cookie.ts","../../src/config/overrides/parse-overrides.ts","../../src/config/microfrontends-config/client/index.ts","../../src/config/microfrontends-config/isomorphic/validation.ts","../../src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts","../../src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts","../../src/config/microfrontends-config/isomorphic/utils/generate-port.ts","../../src/config/microfrontends-config/isomorphic/host.ts","../../src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts","../../src/config/microfrontends-config/isomorphic/application.ts","../../src/config/microfrontends-config/isomorphic/constants.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport {\n type NextFetchEvent,\n NextRequest,\n type MiddlewareConfig,\n} from 'next/server.js';\nimport { match, pathToRegexp } from 'path-to-regexp';\nimport { parse } from 'jsonc-parser';\nimport { MicrofrontendConfigIsomorphic } from '../../config/microfrontends-config/isomorphic';\nimport { DefaultApplication } from '../../config/microfrontends-config/isomorphic/application';\nimport type { Config } from '../../config/schema/types';\n\n/** Replaces path wildcards (if they exist) with synthesized paths. */\nexport function expandWildcards(path: string): string[] {\n if (path.includes('/:path*') || path.includes('/:slug*')) {\n return [\n path === '/:path*' || path === '/:slug*'\n ? '/'\n : path.replace('/:path*', '').replace('/:slug*', ''),\n path.replace('/:path*', '/foo').replace('/:slug*', '/foo'),\n path.replace('/:path*', '/foo/bar').replace('/:slug*', '/foo/bar'),\n ];\n }\n if (path.includes('/:path+') || path.includes('/:slug+')) {\n return [\n path.replace('/:path+', '/foo').replace('/:slug+', '/foo'),\n path.replace('/:path+', '/foo/bar').replace('/:slug+', '/foo/bar'),\n ];\n }\n if (path.includes('/:path') || path.includes('/:slug')) {\n return [path.replace('/:path', '/foo').replace('/:slug', '/foo')];\n }\n return [path];\n}\n\nexport function loadMicrofrontendConfigForEdge(\n path: string,\n): MicrofrontendConfigIsomorphic {\n // NOTE: It's necessary to read and parse this file manually because tests that\n // run in `@edge-runtime/jest-environment` will fail since the AJV validation\n // from the @vercel/microfrontends package violates the rules by\n // using eval.\n const rawMfConfig = parse(readFileSync(path, 'utf-8')) as Config;\n return new MicrofrontendConfigIsomorphic({\n config: rawMfConfig,\n });\n}\n\nexport function getAllChildApplicationNames(\n mfConfig: MicrofrontendConfigIsomorphic,\n): string[] {\n return mfConfig.getChildApplications().map((app) => app.name);\n}\n\nexport function getLaunchedPathsForApp(\n mfConfig: MicrofrontendConfigIsomorphic,\n appName: string,\n): string[] {\n const app = mfConfig.getApplication(appName);\n if (app instanceof DefaultApplication) {\n return [];\n }\n\n return [\n `/${app.getAssetPrefix()}/_next/static`,\n ...app.routing\n .filter((group) => !group.flag)\n .flatMap((group) => group.paths.flatMap(expandWildcards)),\n ];\n}\n\nexport function getFlaggedPathsForApp(\n mfConfig: MicrofrontendConfigIsomorphic,\n appName: string,\n): string[] {\n const app = mfConfig.getApplication(appName);\n if (app instanceof DefaultApplication) {\n return [];\n }\n\n return app.routing\n .filter((group) => Boolean(group.flag))\n .flatMap((group) => group.paths.flatMap(expandWildcards));\n}\n\n/**\n * Returns a list of examples for all paths in microfrontends.json.\n */\nexport function getAllMicrofrontendPaths(\n mfConfig: MicrofrontendConfigIsomorphic,\n): string[] {\n return mfConfig.getChildApplications().flatMap((app) => {\n return app.routing.flatMap((group) => group.paths.flatMap(expandWildcards));\n });\n}\n\nfunction urlMatches(\n middlewareConfig: MiddlewareConfig,\n path: string,\n doNotMatchWithHasOrMissing?: boolean,\n): boolean {\n if (!middlewareConfig.matcher) {\n return false;\n }\n // This is based off\n // https://github.com/vercel/next.js/blob/4835be182b88f67f282c30db4278c30fe9e5b483/packages/next/src/build/analysis/get-page-static-info.ts#L324\n const matchers = Array.isArray(middlewareConfig.matcher)\n ? middlewareConfig.matcher\n : [middlewareConfig.matcher];\n for (let matcher of matchers) {\n matcher = typeof matcher === 'string' ? { source: matcher } : matcher;\n if (match(matcher.source)(path)) {\n if (doNotMatchWithHasOrMissing && (matcher.has || matcher.missing)) {\n return false;\n }\n return true;\n }\n }\n return false;\n}\n\n/**\n * A test to ensure that middleware is configured to work correctly with\n * microfrontends. Passing this test does NOT guarantee middleware is set up\n * correctly, but this should find many common problems. This should only be run\n * on the application marked as \"default\" in the microfrontend config. If a\n * configuration issue is found, this will throw an exception (this ensures it\n * works with any test framework).\n *\n * For example, if a microfrontend is configured to serve \"/my/path\" then the\n * default application should not contain any matcher that matches \"/my/path\".\n *\n * See [documentation](https://vercel.com/docs/microfrontends/troubleshooting#validatemiddlewareconfig) for more information.\n *\n * @example\n * ```ts\n * test('matches microfrontends paths', () => {\n * expect(() =>\n * validateMiddlewareConfig(config, './microfrontends.json'),\n * ).not.toThrow();\n * });\n * ```\n */\nexport function validateMiddlewareConfig(\n middlewareConfig: MiddlewareConfig,\n microfrontendConfigOrPath: string | MicrofrontendConfigIsomorphic,\n extraProductionMatches?: string[],\n): void {\n const microfrontendConfig =\n typeof microfrontendConfigOrPath === 'string'\n ? loadMicrofrontendConfigForEdge(microfrontendConfigOrPath)\n : microfrontendConfigOrPath;\n\n const errors: string[] = [];\n const usedExtraProductionMatches = new Set<string>();\n\n const wellKnownEndpoint = '/.well-known/vercel/microfrontends/client-config';\n if (!urlMatches(middlewareConfig, wellKnownEndpoint)) {\n errors.push(\n `Middleware must be configured to match ${wellKnownEndpoint}. This path is used by the client to know which flagged paths are routed to which microfrontend based on the flag values for the session. See https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher for more information.`,\n );\n }\n\n for (const application of microfrontendConfig.getChildApplications()) {\n const matches = [...application.routing];\n matches.push({\n paths: [`/${application.getAssetPrefix()}/_next/:path+`],\n });\n\n for (const aMatch of matches) {\n const isFlagged = Boolean(aMatch.flag);\n\n for (const path of aMatch.paths) {\n const pathsToTest = expandWildcards(path);\n for (const testPath of pathsToTest) {\n const pathForDisplay = `${testPath}${path === testPath ? '' : ` (synthesized from ${path})`}`;\n\n const productionUrlMatches = urlMatches(middlewareConfig, testPath);\n if (isFlagged) {\n if (!urlMatches(middlewareConfig, testPath, true)) {\n errors.push(\n `Middleware should be configured to match ${pathForDisplay}. Middleware config matchers for flagged paths should ALWAYS match.`,\n );\n // Skip the remaining expanded wildcard paths (if there are any)\n // to only report a single error per wildcard.\n break;\n }\n } else if (productionUrlMatches) {\n if (extraProductionMatches?.includes(path)) {\n usedExtraProductionMatches.add(path);\n } else {\n errors.push(\n `Middleware should not match ${pathForDisplay}. This path is routed to a microfrontend and will never reach the middleware for the default application.`,\n );\n }\n // Skip the remaining expanded wildcard paths (if there are any)\n // to only report a single error per wildcard.\n break;\n }\n }\n }\n }\n }\n\n const unusedExtraProductionMatches = extraProductionMatches?.filter(\n (x) => !usedExtraProductionMatches.has(x),\n );\n if (unusedExtraProductionMatches?.length) {\n errors.push(\n `The following paths were passed to the extraProductionMatches parameter but were unused. You probably want to remove them from the extraProductionMatches parameter: ${unusedExtraProductionMatches.join(', ')}`,\n );\n }\n\n if (errors.length > 0) {\n const message = `Found the following inconsistencies between your microfrontend config ${\n typeof microfrontendConfigOrPath === 'string'\n ? `(at ${microfrontendConfigOrPath}) `\n : ''\n }and middleware config:\\n\\n- `;\n throw new Error(message + errors.join('\\n\\n- '));\n }\n}\n\n/**\n * Ensures that middleware rewrites to the correct path for flagged paths.\n * IMPORTANT: you must enable the necessary flags before calling this function.\n *\n * See [documentation](https://vercel.com/docs/microfrontends/troubleshooting#validatemiddlewareonflaggedpaths) for more information.\n *\n * @example\n * ```ts\n * jest.mock('flags/next', () => ({\n * flag: jest.fn().mockReturnValue(jest.fn().mockResolvedValue(true)),\n * }));\n *\n * test('matches microfrontends paths', () => {\n * await expect(\n * validateMiddlewareOnFlaggedPaths('./microfrontends.json', middleware),\n * ).resolves.not.toThrow();\n * });\n * ```\n */\nexport async function validateMiddlewareOnFlaggedPaths(\n microfrontendConfigOrPath: string | MicrofrontendConfigIsomorphic,\n middleware: (\n request: NextRequest,\n event: NextFetchEvent,\n ) => Promise<Response | undefined>,\n): Promise<void> {\n const initialEnv = process.env.VERCEL_ENV;\n const initialMfePreviewDomains = process.env.MFE_PREVIEW_DOMAINS;\n try {\n const microfrontendConfig =\n typeof microfrontendConfigOrPath === 'string'\n ? loadMicrofrontendConfigForEdge(microfrontendConfigOrPath)\n : microfrontendConfigOrPath;\n const allAppNames = getAllChildApplicationNames(microfrontendConfig);\n\n const errors: string[] = [];\n for (const appName of allAppNames) {\n const flaggedPaths = getFlaggedPathsForApp(microfrontendConfig, appName);\n if (flaggedPaths.length) {\n for (const path of flaggedPaths) {\n const host =\n microfrontendConfig.defaultApplication.fallback.toString();\n const requestPath = `${host}${path}`;\n const request = new NextRequest(requestPath);\n\n // eslint-disable-next-line no-await-in-loop\n const response = await middleware(\n request,\n {} as unknown as NextFetchEvent,\n );\n const routedZone = response?.headers.get(\n 'x-middleware-request-x-vercel-mfe-zone',\n );\n if (!response) {\n errors.push(\n `middleware did not action for ${requestPath}. Expected to route to ${appName}`,\n );\n } else if (response.status !== 200) {\n errors.push(\n `expected 200 status for ${requestPath} but got ${response.status}`,\n );\n } else if (routedZone !== appName) {\n errors.push(\n `expected ${requestPath} to route to ${appName}, but got ${routedZone}`,\n );\n }\n }\n }\n }\n if (errors.length) {\n throw new Error(errors.join('\\n'));\n }\n } finally {\n process.env.VERCEL_ENV = initialEnv;\n process.env.MFE_PREVIEW_DOMAINS = initialMfePreviewDomains;\n }\n}\n\n/**\n * Validates that the given paths route to the correct microfrontend.\n * The `routesToTest` parameter is a record mapping the application name\n * to a list a paths (with an optional flag) that should be routed to that\n * application. If an issue is found, this will throw an exception so that\n * it can be used with any test framework.\n *\n * See [documentation](https://vercel.com/docs/microfrontends/troubleshooting#validaterouting) for more information.\n *\n * For example:\n *\n * ```ts\n * {\n * 'microfrontend-a': ['/a/path', '/a/longer/path'],\n * 'microfrontend-b': ['/b/path'],\n * 'microfrontend-c': [\n * '/c/path',\n * {\n * 'path': '/c/flagged',\n * 'flag': 'my-flag',\n * }\n * ],\n * }\n * ```\n *\n * This ensures:\n * - `/a/path` and `/a/longer/path` get routed to `microfrontend-a`\n * - `/b/path` gets routed to `microfrontend-b`\n * - `/c/flagged` gets routed to `microfrontend-c` if `my-flag` is enabled.\n */\nexport function validateRouting(\n microfrontendConfigOrPath: string | MicrofrontendConfigIsomorphic,\n routesToTest: Record<string, (string | { path: string; flag: string })[]>,\n) {\n const microfrontendConfig =\n typeof microfrontendConfigOrPath === 'string'\n ? loadMicrofrontendConfigForEdge(microfrontendConfigOrPath)\n : microfrontendConfigOrPath;\n const matches = new Map<{ path: string; flag?: string }, string>();\n for (const application of microfrontendConfig.getChildApplications()) {\n for (const route of application.routing) {\n for (const path of route.paths) {\n matches.set({ path, flag: route.flag }, application.name);\n }\n }\n }\n const errors = [];\n for (const [applicationName, paths] of Object.entries(routesToTest)) {\n if (!microfrontendConfig.hasApplication(applicationName)) {\n errors.push(\n `Application ${applicationName} does not exist in the microfrontends config. The applications in the config are: ${microfrontendConfig\n .getAllApplications()\n .map((app) => app.name)\n .join(', ')}`,\n );\n continue;\n }\n for (const expected of paths) {\n const path = typeof expected === 'string' ? expected : expected.path;\n const flag = typeof expected === 'string' ? undefined : expected.flag;\n const matchedApplications = new Map<string, string[]>();\n const matchesWithoutFlags = new Map<string, string>();\n\n for (const [matcher, applicationMatched] of matches.entries()) {\n if (pathToRegexp(matcher.path).test(path)) {\n if (!matcher.flag || matcher.flag === flag) {\n const existingMatches =\n matchedApplications.get(applicationMatched) ?? [];\n existingMatches.push(matcher.path);\n matchedApplications.set(applicationMatched, existingMatches);\n } else {\n // This path would've matched this application if this flag was set.\n matchesWithoutFlags.set(applicationName, matcher.flag);\n }\n }\n }\n if (matchedApplications.size === 0) {\n matchedApplications.set(\n microfrontendConfig.getDefaultApplication().name,\n ['fallback to default application'],\n );\n }\n if (matchedApplications.size > 1) {\n const formattedMatches = Array.from(\n matchedApplications\n .entries()\n .map(\n ([matchedApplication, matchers]) =>\n `${matchedApplication} (on ${matchers.join(', ')})`,\n ),\n ).join(', ');\n errors.push(\n `${path} can only match one application, but it matched multiple: ${formattedMatches}`,\n );\n } else if (!matchedApplications.has(applicationName)) {\n const actualMatch = matchedApplications.entries().next().value;\n if (!actualMatch) {\n throw new Error(\"this shouldn't happen\");\n }\n const [matchedApplication, matchers] = actualMatch;\n let extraMessage = '';\n if (matchesWithoutFlags.has(applicationName)) {\n const flagToSet = matchesWithoutFlags.get(applicationName);\n extraMessage = ` It would've matched ${applicationName} if the ${flagToSet} flag was set. If this is what you want, replace ${path} in the paths-to-test list with {path: '${path}', flag: '${flagToSet}'}.`;\n }\n errors.push(\n `Expected ${path}${flag ? ` (with flag ${flag})` : ''} to match ${applicationName}, but it matched ${matchedApplication} (on ${matchers.join(', ')}).${extraMessage}`,\n );\n }\n }\n }\n if (errors.length) {\n throw new Error(\n `Incorrect microfrontends routing detected:\\n\\n- ${errors.join('\\n- ')}`,\n );\n }\n}\n","import { parse } from 'jsonc-parser';\nimport { getConfigStringFromEnv } from '../utils/get-config-from-env';\nimport { isDefaultApp } from '../../schema/utils/is-default-app';\nimport type { Config } from '../../schema/types';\nimport { MicrofrontendError } from '../../errors';\nimport { type OverridesConfig, parseOverrides } from '../../overrides';\nimport type { ClientConfig } from '../client/types';\nimport { MicrofrontendConfigClient } from '../client';\nimport { DefaultApplication, ChildApplication } from './application';\nimport { DEFAULT_LOCAL_PROXY_PORT } from './constants';\nimport {\n validateConfigDefaultApplication,\n validateConfigPaths,\n} from './validation';\nimport { hashApplicationName } from './utils/hash-application-name';\n\n/**\n * A class to manage the microfrontends configuration.\n */\nexport class MicrofrontendConfigIsomorphic {\n config: Config;\n defaultApplication: DefaultApplication;\n childApplications: Record<string, ChildApplication> = {};\n overrides?: OverridesConfig;\n options?: Config['options'];\n\n private readonly serialized: {\n config: Config;\n overrides?: OverridesConfig;\n };\n\n constructor({\n config,\n overrides,\n }: {\n config: Config;\n overrides?: OverridesConfig;\n }) {\n // run validation on init\n MicrofrontendConfigIsomorphic.validate(config);\n\n const disableOverrides = config.options?.disableOverrides ?? false;\n this.overrides = overrides && !disableOverrides ? overrides : undefined;\n\n let defaultApplication: DefaultApplication | undefined;\n // create applications\n for (const [appId, appConfig] of Object.entries(config.applications)) {\n const appOverrides = !disableOverrides\n ? this.overrides?.applications[appId]\n : undefined;\n\n if (isDefaultApp(appConfig)) {\n defaultApplication = new DefaultApplication(appId, {\n app: appConfig,\n overrides: appOverrides,\n });\n } else {\n this.childApplications[appId] = new ChildApplication(appId, {\n app: appConfig,\n overrides: appOverrides,\n });\n }\n }\n\n // validate that this.defaultApplication is defined\n if (!defaultApplication) {\n throw new MicrofrontendError(\n 'Could not find default application in microfrontends configuration',\n {\n type: 'application',\n subtype: 'not_found',\n },\n );\n }\n this.defaultApplication = defaultApplication;\n\n this.config = config;\n this.options = config.options;\n this.serialized = {\n config,\n overrides,\n };\n }\n\n static validate(config: string | Config): Config {\n // let this throw if it's not valid JSON\n const c = typeof config === 'string' ? (parse(config) as Config) : config;\n\n validateConfigPaths(c.applications);\n validateConfigDefaultApplication(c.applications);\n\n return c;\n }\n\n static fromEnv({\n cookies,\n }: {\n cookies?: { name: string; value: string }[];\n }): MicrofrontendConfigIsomorphic {\n return new MicrofrontendConfigIsomorphic({\n config: parse(getConfigStringFromEnv()) as Config,\n overrides: parseOverrides(cookies ?? []),\n });\n }\n\n isOverridesDisabled(): boolean {\n return this.options?.disableOverrides ?? false;\n }\n\n getConfig(): Config {\n return this.config;\n }\n\n getApplicationsByType(): {\n defaultApplication?: DefaultApplication;\n applications: ChildApplication[];\n } {\n return {\n defaultApplication: this.defaultApplication,\n applications: Object.values(this.childApplications),\n };\n }\n\n getChildApplications(): ChildApplication[] {\n return Object.values(this.childApplications);\n }\n\n getAllApplications(): (DefaultApplication | ChildApplication)[] {\n return [\n this.defaultApplication,\n ...Object.values(this.childApplications),\n ].filter(Boolean);\n }\n\n getApplication(name: string): DefaultApplication | ChildApplication {\n // check the default\n if (\n this.defaultApplication.name === name ||\n this.defaultApplication.packageName === name\n ) {\n return this.defaultApplication;\n }\n const app =\n this.childApplications[name] ||\n Object.values(this.childApplications).find(\n (child) => child.packageName === name,\n );\n if (!app) {\n throw new MicrofrontendError(\n `Could not find microfrontends configuration for application \"${name}\". If the name in package.json 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 {\n type: 'application',\n subtype: 'not_found',\n },\n );\n }\n\n return app;\n }\n\n hasApplication(name: string): boolean {\n try {\n this.getApplication(name);\n return true;\n } catch {\n return false;\n }\n }\n\n getApplicationByProjectName(\n projectName: string,\n ): DefaultApplication | ChildApplication | undefined {\n // check the default\n if (this.defaultApplication.name === projectName) {\n return this.defaultApplication;\n }\n\n return Object.values(this.childApplications).find(\n (app) => app.name === projectName,\n );\n }\n\n /**\n * Returns the default application.\n */\n getDefaultApplication(): DefaultApplication {\n return this.defaultApplication;\n }\n\n /**\n * Returns the configured port for the local proxy\n */\n getLocalProxyPort(): number {\n return this.config.options?.localProxyPort ?? DEFAULT_LOCAL_PROXY_PORT;\n }\n\n toClientConfig(options?: {\n removeFlaggedPaths?: boolean;\n }): MicrofrontendConfigClient {\n const applications: ClientConfig['applications'] = Object.fromEntries(\n Object.entries(this.childApplications).map(([name, application]) => [\n hashApplicationName(name),\n {\n default: false,\n routing: application.routing,\n },\n ]),\n );\n\n applications[hashApplicationName(this.defaultApplication.name)] = {\n default: true,\n };\n\n return new MicrofrontendConfigClient(\n {\n applications,\n },\n {\n removeFlaggedPaths: options?.removeFlaggedPaths,\n },\n );\n }\n\n /**\n * Serializes the class back to the Schema type.\n *\n * NOTE: This is used when writing the config to disk and must always match the input Schema\n */\n toSchemaJson(): Config {\n return this.serialized.config;\n }\n\n serialize(): {\n config: Config;\n overrides?: OverridesConfig;\n } {\n return this.serialized;\n }\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","import { MicrofrontendError } from '../../errors';\n\n/**\n * Utility to fetch the microfrontend configuration string from the environment.\n */\nexport function getConfigStringFromEnv(): string {\n const config = process.env.MFE_CONFIG;\n if (!config) {\n throw new MicrofrontendError(`Missing \"MFE_CONFIG\" in environment.`, {\n type: 'config',\n subtype: 'not_found_in_env',\n });\n }\n return config;\n}\n","import type { Application, DefaultApplication } from '../types';\n\nexport function isDefaultApp(a: Application): a is DefaultApplication {\n return !('routing' in a);\n}\n","// cookie name needs to match proxy\n// https://github.com/vercel/proxy/blob/fb00d723136ad539a194e4a851dd272010527c35/lib/routing/micro_frontends_overrides.lua#L7\nexport const OVERRIDES_COOKIE_PREFIX = 'vercel-micro-frontends-override';\nexport const OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;\n","import { OVERRIDES_COOKIE_PREFIX } from './constants';\n\nexport function isOverrideCookie(cookie: { name?: string }): boolean {\n return Boolean(cookie.name?.startsWith(OVERRIDES_COOKIE_PREFIX));\n}\n","import { isOverrideCookie } from './is-override-cookie';\nimport { OVERRIDES_ENV_COOKIE_PREFIX } from './constants';\n\nexport function getOverrideFromCookie(cookie: {\n name: string;\n value?: string | null;\n}): { application: string; host: string } | undefined {\n if (!isOverrideCookie(cookie) || !cookie.value) return;\n return {\n application: cookie.name.replace(OVERRIDES_ENV_COOKIE_PREFIX, ''),\n host: cookie.value,\n };\n}\n","import type { OverridesConfig } from './types';\nimport { getOverrideFromCookie } from './get-override-from-cookie';\n\nexport function parseOverrides(\n cookies: { name: string; value?: string | null }[],\n): OverridesConfig {\n const overridesConfig: OverridesConfig = { applications: {} };\n\n cookies.forEach((cookie) => {\n const override = getOverrideFromCookie(cookie);\n if (!override) return;\n overridesConfig.applications[override.application] = {\n environment: { host: override.host },\n };\n });\n\n return overridesConfig;\n}\n","import { pathToRegexp } from 'path-to-regexp';\nimport type { ClientConfig } from './types';\n\nexport interface MicrofrontendConfigClientOptions {\n removeFlaggedPaths?: boolean;\n}\n\nconst regexpCache = new Map<string, RegExp>();\nconst getRegexp = (path: string): RegExp => {\n const existing = regexpCache.get(path);\n if (existing) {\n return existing;\n }\n\n const regexp = pathToRegexp(path);\n regexpCache.set(path, regexp);\n return regexp;\n};\n\nexport class MicrofrontendConfigClient {\n applications: ClientConfig['applications'];\n hasFlaggedPaths: boolean;\n pathCache: Record<string, string> = {};\n private readonly serialized: ClientConfig;\n\n constructor(config: ClientConfig, opts?: MicrofrontendConfigClientOptions) {\n this.hasFlaggedPaths = config.hasFlaggedPaths ?? false;\n for (const app of Object.values(config.applications)) {\n if (app.routing) {\n if (app.routing.some((match) => match.flag)) {\n this.hasFlaggedPaths = true;\n }\n const newRouting = [];\n const pathsWithoutFlags = [];\n for (const group of app.routing) {\n if (group.flag) {\n if (opts?.removeFlaggedPaths) {\n continue;\n }\n if (group.group) {\n delete group.group;\n }\n newRouting.push(group);\n } else {\n pathsWithoutFlags.push(...group.paths);\n }\n }\n if (pathsWithoutFlags.length > 0) {\n newRouting.push({ paths: pathsWithoutFlags });\n }\n app.routing = newRouting;\n }\n }\n this.serialized = config;\n if (this.hasFlaggedPaths) {\n this.serialized.hasFlaggedPaths = this.hasFlaggedPaths;\n }\n this.applications = config.applications;\n }\n\n /**\n * Create a new `MicrofrontendConfigClient` from a JSON string.\n * Config must be passed in to remain framework agnostic\n */\n static fromEnv(config: string | undefined): MicrofrontendConfigClient {\n if (!config) {\n throw new Error(\n 'Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?',\n );\n }\n return new MicrofrontendConfigClient(JSON.parse(config) as ClientConfig);\n }\n\n isEqual(other: MicrofrontendConfigClient): boolean {\n return (\n this === other ||\n JSON.stringify(this.applications) === JSON.stringify(other.applications)\n );\n }\n\n getApplicationNameForPath(path: string): string | null {\n if (!path.startsWith('/')) {\n throw new Error(`Path must start with a /`);\n }\n\n if (this.pathCache[path]) {\n return this.pathCache[path];\n }\n\n const pathname = new URL(path, 'https://example.com').pathname;\n for (const [name, application] of Object.entries(this.applications)) {\n if (application.routing) {\n for (const group of application.routing) {\n for (const childPath of group.paths) {\n const regexp = getRegexp(childPath);\n if (regexp.test(pathname)) {\n this.pathCache[path] = name;\n return name;\n }\n }\n }\n }\n }\n const defaultApplication = Object.entries(this.applications).find(\n ([, application]) => application.default,\n );\n if (!defaultApplication) {\n return null;\n }\n\n this.pathCache[path] = defaultApplication[0];\n return defaultApplication[0];\n }\n\n serialize(): ClientConfig {\n return this.serialized;\n }\n}\n","import { pathToRegexp, parse as parsePathRegexp } from 'path-to-regexp';\nimport type {\n ApplicationId,\n PathGroup,\n ApplicationRouting,\n ChildApplication as ChildApplicationConfig,\n} from '../../schema/types';\nimport { MicrofrontendError } from '../../errors';\nimport { isDefaultApp } from '../../schema/utils/is-default-app';\n\nconst LIST_FORMATTER = new Intl.ListFormat('en', {\n style: 'long',\n type: 'conjunction',\n});\n\nconst VALID_ASSET_PREFIX_REGEXP = /^[a-z](?:[a-z0-9-]*[a-z0-9])?$/;\n\n/**\n * Validate all paths in a configuration - ensures paths do not overlap\n */\nexport const validateConfigPaths = (\n applicationConfigsById?: ApplicationRouting,\n): void => {\n if (!applicationConfigsById) {\n return;\n }\n\n const pathsByApplicationId = new Map<\n PathGroup['paths'][number],\n {\n applications: ApplicationId[];\n matcher: RegExp;\n applicationId?: ApplicationId;\n }\n >();\n const errors: string[] = [];\n\n for (const [id, app] of Object.entries(applicationConfigsById)) {\n if (isDefaultApp(app)) {\n // default applications do not have routing\n continue;\n }\n\n for (const pathMatch of app.routing) {\n for (const path of pathMatch.paths) {\n const maybeError = validatePathExpression(path);\n if (maybeError) {\n errors.push(maybeError);\n } else {\n const existing = pathsByApplicationId.get(path);\n if (existing) {\n existing.applications.push(id);\n } else {\n pathsByApplicationId.set(path, {\n applications: [id],\n matcher: pathToRegexp(path),\n applicationId: id,\n });\n }\n }\n }\n }\n }\n const entries = Array.from(pathsByApplicationId.entries());\n\n for (const [path, { applications: ids, matcher, applicationId }] of entries) {\n if (ids.length > 1) {\n errors.push(\n `Duplicate path \"${path}\" for applications \"${ids.join(', ')}\"`,\n );\n }\n\n for (const [\n matchPath,\n { applications: matchIds, applicationId: matchApplicationId },\n ] of entries) {\n if (path === matchPath) {\n // we're comparing to ourselves, so skip\n continue;\n }\n\n if (applicationId === matchApplicationId) {\n // we're comparing to paths within our own application, which are allowed to overlap, so skip\n continue;\n }\n\n if (matcher.test(matchPath)) {\n const source = `\"${path}\" of application${ids.length > 0 ? 's' : ''} ${ids.join(', ')}`;\n const destination = `\"${matchPath}\" of application${matchIds.length > 0 ? 's' : ''} ${matchIds.join(', ')}`;\n\n errors.push(\n `Overlapping path detected between ${source} and ${destination}`,\n );\n }\n }\n }\n\n if (errors.length) {\n throw new MicrofrontendError(\n `Invalid paths: ${errors.join(', ')}. See supported paths in the documentation https://vercel.com/docs/microfrontends/path-routing#supported-path-expressions.`,\n {\n type: 'config',\n subtype: 'conflicting_paths',\n },\n );\n }\n};\n\n// From https://github.com/pillarjs/path-to-regexp/blob/b0778f5e8e6c6e9ee4e2f5b34e877cc5229f8036/src/index.ts#L143\nconst PATH_DEFAULT_PATTERN = '[^\\\\/#\\\\?]+?';\n\nfunction validatePathExpression(path: string): string | undefined {\n try {\n const tokens = parsePathRegexp(path);\n if (/(?<!\\\\)\\{/.test(path)) {\n return `Optional paths are not supported: ${path}`;\n }\n if (/(?<!\\\\|\\()\\?/.test(path)) {\n return `Optional paths are not supported: ${path}`;\n }\n if (/\\/[^/]*(?<!\\\\):[^/]*(?<!\\\\):[^/]*/.test(path)) {\n return `Only one wildcard is allowed per path segment: ${path}`;\n }\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n if (token === undefined) {\n return `token ${i} in ${path} is undefined, this shouldn't happen`;\n }\n if (typeof token !== 'string') {\n if (!token.name) {\n return `Only named wildcards are allowed: ${path} (hint: add \":path\" to the wildcard)`;\n }\n if (\n token.pattern !== PATH_DEFAULT_PATTERN &&\n // Allows (a|b|c) and ((?!a|b|c).*) regex\n // Only limited regex is supported for now, due to performance considerations\n !/^(?<allowed>[\\w]+(?:\\|[^:|()]+)+)$|^\\(\\?!(?<disallowed>[\\w]+(?:\\|[^:|()]+)*)\\)\\.\\*$/.test(\n token.pattern,\n )\n ) {\n return `Path ${path} cannot use unsupported regular expression wildcard`;\n }\n if (token.modifier && i !== tokens.length - 1) {\n return `Modifier ${token.modifier} is not allowed on wildcard :${token.name} in ${path}. Modifiers are only allowed in the last path component`;\n }\n }\n }\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return `Path ${path} could not be parsed into regexp: ${message}`;\n }\n return undefined;\n}\n\n/**\n * Validate all paths in an application - ensures paths are the correct format\n */\nexport const validateAppPaths = (\n name: string,\n app: ChildApplicationConfig,\n): void => {\n // validate routes\n for (const group of app.routing) {\n for (const p of group.paths) {\n if (p === '/') {\n continue;\n }\n if (p.endsWith('/')) {\n throw new MicrofrontendError(\n `Invalid path for application \"${name}\". ${p} must not end with a slash.`,\n { type: 'application', subtype: 'invalid_path' },\n );\n }\n\n if (!p.startsWith('/')) {\n throw new MicrofrontendError(\n `Invalid path for application \"${name}\". ${p} must start with a slash.`,\n { type: 'application', subtype: 'invalid_path' },\n );\n }\n }\n }\n if (app.assetPrefix) {\n if (!VALID_ASSET_PREFIX_REGEXP.test(app.assetPrefix)) {\n throw new MicrofrontendError(\n `Invalid asset prefix for application \"${name}\". ${app.assetPrefix} must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`,\n { type: 'application', subtype: 'invalid_asset_prefix' },\n );\n }\n if (\n app.assetPrefix !== `vc-ap-${name}` &&\n !app.routing.some(\n (group) =>\n group.paths.includes(`/${app.assetPrefix}/:path*`) && !group.flag,\n )\n ) {\n throw new MicrofrontendError(\n `When \\`assetPrefix\\` is specified, \\`/${app.assetPrefix}/:path*\\` must be added the routing paths for the application. Changing the asset prefix is not a forwards and backwards compatible change, and the custom asset prefix should be added to \\`paths\\` and deployed before setting the \\`assetPrefix\\` field.`,\n { type: 'application', subtype: 'invalid_asset_prefix' },\n );\n }\n }\n};\n\n/**\n * Make sure only one `Application` defines routing\n * */\nexport const validateConfigDefaultApplication = (\n applicationConfigsById?: ApplicationRouting,\n): void => {\n if (!applicationConfigsById) {\n return;\n }\n\n const applicationsWithoutRouting = Object.entries(\n applicationConfigsById,\n ).filter(([, app]) => isDefaultApp(app));\n const numApplicationsWithoutRouting = applicationsWithoutRouting.reduce(\n (acc) => {\n return acc + 1;\n },\n 0,\n );\n\n if (numApplicationsWithoutRouting === 0) {\n throw new MicrofrontendError(\n 'No default application found. At least one application needs to be the default by omitting routing.',\n { type: 'config', subtype: 'no_default_application' },\n );\n }\n\n if (numApplicationsWithoutRouting > 1) {\n const applicationNamesMissingRouting = applicationsWithoutRouting.map(\n ([name]) => name,\n );\n throw new MicrofrontendError(\n `All applications except for the default app must contain the \"routing\" field. Applications that are missing routing: ${LIST_FORMATTER.format(applicationNamesMissingRouting)}.`,\n { type: 'config', subtype: 'multiple_default_applications' },\n );\n }\n};\n","import md5 from 'md5';\n\nexport function hashApplicationName(name: string): string {\n if (!name) {\n throw new Error('Application name is required to generate hash');\n }\n\n return md5(name).substring(0, 6).padStart(6, '0');\n}\n","import { hashApplicationName } from './hash-application-name';\n\nconst PREFIX = 'vc-ap';\n\nexport function generateAssetPrefixFromName({\n name,\n}: {\n name: string;\n}): string {\n if (!name) {\n throw new Error('Name is required to generate an asset prefix');\n }\n\n return `${PREFIX}-${hashApplicationName(name)}`;\n}\n","export function generatePortFromName({\n name,\n minPort = 3000,\n maxPort = 8000,\n}: {\n name: string;\n minPort?: number;\n maxPort?: number;\n}): number {\n if (!name) {\n throw new Error('Name is required to generate a port');\n }\n\n // hash the name\n let hash = 0;\n for (let i = 0; i < name.length; i++) {\n // eslint-disable-next-line no-bitwise\n hash = (hash << 5) - hash + name.charCodeAt(i);\n // Convert to 32-bit\n // eslint-disable-next-line no-bitwise\n hash |= 0;\n }\n hash = Math.abs(hash);\n\n // Map the hash to the port range\n const range = maxPort - minPort;\n const port = minPort + (hash % range);\n\n return port;\n}\n","import type {\n HostConfig as RemoteHostConfigSchema,\n LocalHostConfig as LocalHostConfigSchema,\n} from '../../../bin/types';\nimport { generatePortFromName } from './utils/generate-port';\n\ninterface HostOptions {\n isLocal?: boolean;\n}\n\nexport class Host {\n protocol: 'http' | 'https';\n host: string;\n port?: number;\n local: boolean | undefined;\n\n constructor(\n hostConfig: RemoteHostConfigSchema | string,\n options?: HostOptions,\n ) {\n if (typeof hostConfig === 'string') {\n ({\n protocol: this.protocol,\n host: this.host,\n port: this.port,\n } = Host.parseUrl(hostConfig));\n } else {\n const { protocol = 'https', host, port } = hostConfig;\n this.protocol = protocol;\n this.host = host;\n this.port = port;\n }\n this.local = options?.isLocal;\n }\n\n protected static parseUrl(\n url: string,\n defaultProtocol = 'https',\n ): {\n protocol: Host['protocol'];\n host: string;\n port?: number;\n } {\n let hostToParse = url;\n if (!/^https?:\\/\\//.exec(hostToParse)) {\n hostToParse = `${defaultProtocol}://${hostToParse}`;\n }\n const parsed = new URL(hostToParse);\n if (!parsed.hostname) {\n throw new Error(Host.getMicrofrontendsError(url, 'requires a host'));\n }\n if (parsed.hash) {\n throw new Error(\n Host.getMicrofrontendsError(url, 'cannot have a fragment'),\n );\n }\n if (parsed.username || parsed.password) {\n throw new Error(\n Host.getMicrofrontendsError(\n url,\n 'cannot have authentication credentials (username and/or password)',\n ),\n );\n }\n if (parsed.pathname !== '/') {\n throw new Error(Host.getMicrofrontendsError(url, 'cannot have a path'));\n }\n if (parsed.search) {\n throw new Error(\n Host.getMicrofrontendsError(url, 'cannot have query parameters'),\n );\n }\n const protocol = parsed.protocol.slice(0, -1) as Host['protocol'];\n return {\n protocol,\n host: parsed.hostname,\n port: parsed.port ? Number.parseInt(parsed.port) : undefined,\n };\n }\n\n private static getMicrofrontendsError(url: string, message: string): string {\n return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;\n }\n\n isLocal(): boolean {\n return this.local || this.host === 'localhost' || this.host === '127.0.0.1';\n }\n\n toString(): string {\n const url = this.toUrl();\n // strip the trailing slash\n return url.toString().replace(/\\/$/, '');\n }\n\n toUrl(): URL {\n const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ''}`;\n return new URL(url);\n }\n}\n\n/**\n * A Host subclass with defaults for locally running applications\n */\nexport class LocalHost extends Host {\n constructor({\n appName,\n local,\n }: {\n appName: string;\n local?: string | number | LocalHostConfigSchema;\n }) {\n let protocol: RemoteHostConfigSchema['protocol'];\n let host: string | undefined;\n let port: number | undefined;\n if (typeof local === 'number') {\n port = local;\n } else if (typeof local === 'string') {\n if (/^\\d+$/.test(local)) {\n port = Number.parseInt(local);\n } else {\n const parsed = Host.parseUrl(local, 'http');\n protocol = parsed.protocol;\n host = parsed.host;\n port = parsed.port;\n }\n } else if (local) {\n protocol = local.protocol;\n host = local.host;\n port = local.port;\n }\n // set defaults for local\n super({\n protocol: protocol ?? 'http',\n host: host ?? 'localhost',\n port: port ?? generatePortFromName({ name: appName }),\n });\n }\n}\n","export function generateAutomationBypassEnvVarName({\n name,\n}: {\n name: string;\n}): string {\n return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, '_')}`;\n}\n","import type {\n Application as ApplicationConfig,\n DefaultApplication as DefaultApplicationConfig,\n ChildApplication as ChildApplicationConfig,\n PathGroup,\n} from '../../schema/types';\nimport type { ApplicationOverrideConfig } from '../../overrides';\nimport { validateAppPaths } from './validation';\nimport { generateAssetPrefixFromName } from './utils/generate-asset-prefix';\nimport { Host, LocalHost } from './host';\nimport { generateAutomationBypassEnvVarName } from './utils/generate-automation-bypass-env-var-name';\n\nexport class Application {\n readonly default: boolean;\n name: string;\n development: {\n local: LocalHost;\n fallback?: Host;\n };\n fallback?: Host;\n packageName?: string;\n overrides?: {\n environment?: Host;\n };\n readonly serialized: ApplicationConfig;\n\n constructor(\n name: string,\n {\n app,\n overrides,\n isDefault,\n }: {\n app: ApplicationConfig;\n overrides?: ApplicationOverrideConfig;\n isDefault?: boolean;\n },\n ) {\n this.name = name;\n this.development = {\n local: new LocalHost({\n appName: name,\n local: app.development?.local,\n }),\n fallback: app.development?.fallback\n ? new Host(app.development.fallback)\n : undefined,\n };\n if (app.development?.fallback) {\n this.fallback = new Host(app.development.fallback);\n }\n this.packageName = app.packageName;\n this.overrides = overrides?.environment\n ? {\n environment: new Host(overrides.environment),\n }\n : undefined;\n this.default = isDefault ?? false;\n this.serialized = app;\n }\n\n isDefault(): boolean {\n return this.default;\n }\n\n getAssetPrefix(): string {\n const generatedAssetPrefix = generateAssetPrefixFromName({\n name: this.name,\n });\n if ('assetPrefix' in this.serialized) {\n return this.serialized.assetPrefix ?? generatedAssetPrefix;\n }\n return generatedAssetPrefix;\n }\n\n getAutomationBypassEnvVarName(): string {\n return generateAutomationBypassEnvVarName({ name: this.name });\n }\n\n serialize(): ApplicationConfig {\n return this.serialized;\n }\n}\n\nexport class DefaultApplication extends Application {\n readonly default = true;\n fallback: Host;\n\n constructor(\n name: string,\n {\n app,\n overrides,\n }: {\n app: DefaultApplicationConfig;\n overrides?: ApplicationOverrideConfig;\n },\n ) {\n super(name, {\n app,\n overrides,\n isDefault: true,\n });\n\n this.fallback = new Host(app.development.fallback);\n }\n\n getAssetPrefix(): string {\n return '';\n }\n}\n\nexport class ChildApplication extends Application {\n readonly default = false;\n routing: PathGroup[];\n\n constructor(\n name: string,\n {\n app,\n overrides,\n }: {\n app: ChildApplicationConfig;\n overrides?: ApplicationOverrideConfig;\n },\n ) {\n // validate\n ChildApplication.validate(name, app);\n\n super(name, {\n app,\n overrides,\n isDefault: false,\n });\n\n this.routing = app.routing;\n }\n\n static validate(name: string, app: ChildApplicationConfig): void {\n // validate routes\n validateAppPaths(name, app);\n }\n}\n","export const DEFAULT_LOCAL_PROXY_PORT = 3024;\n"],"mappings":"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","names":["pathToRegexp","parse","match","pathToRegexp","pathToRegexp","parse","pathToRegexp"]}
|
|
1
|
+
{"version":3,"sources":["../../src/next/testing/index.ts","../../src/config/microfrontends-config/isomorphic/index.ts","../../src/config/errors.ts","../../src/config/microfrontends-config/utils/get-config-from-env.ts","../../src/config/schema/utils/is-default-app.ts","../../src/config/overrides/constants.ts","../../src/config/overrides/is-override-cookie.ts","../../src/config/overrides/get-override-from-cookie.ts","../../src/config/overrides/parse-overrides.ts","../../src/config/microfrontends-config/client/index.ts","../../src/config/microfrontends-config/isomorphic/validation.ts","../../src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts","../../src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts","../../src/config/microfrontends-config/isomorphic/utils/generate-port.ts","../../src/config/microfrontends-config/isomorphic/host.ts","../../src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts","../../src/config/microfrontends-config/isomorphic/application.ts","../../src/config/microfrontends-config/isomorphic/constants.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport {\n type NextFetchEvent,\n NextRequest,\n type MiddlewareConfig,\n} from 'next/server.js';\nimport { match, pathToRegexp } from 'path-to-regexp';\nimport { parse } from 'jsonc-parser';\nimport { MicrofrontendConfigIsomorphic } from '../../config/microfrontends-config/isomorphic';\nimport { DefaultApplication } from '../../config/microfrontends-config/isomorphic/application';\nimport type { Config } from '../../config/schema/types';\n\n/** Replaces path wildcards (if they exist) with synthesized paths. */\nexport function expandWildcards(path: string): string[] {\n if (path.includes('/:path*') || path.includes('/:slug*')) {\n return [\n path === '/:path*' || path === '/:slug*'\n ? '/'\n : path.replace('/:path*', '').replace('/:slug*', ''),\n path.replace('/:path*', '/foo').replace('/:slug*', '/foo'),\n path.replace('/:path*', '/foo/bar').replace('/:slug*', '/foo/bar'),\n ];\n }\n if (path.includes('/:path+') || path.includes('/:slug+')) {\n return [\n path.replace('/:path+', '/foo').replace('/:slug+', '/foo'),\n path.replace('/:path+', '/foo/bar').replace('/:slug+', '/foo/bar'),\n ];\n }\n if (path.includes('/:path') || path.includes('/:slug')) {\n return [path.replace('/:path', '/foo').replace('/:slug', '/foo')];\n }\n return [path];\n}\n\nexport function loadMicrofrontendConfigForEdge(\n path: string,\n): MicrofrontendConfigIsomorphic {\n // NOTE: It's necessary to read and parse this file manually because tests that\n // run in `@edge-runtime/jest-environment` will fail since the AJV validation\n // from the @vercel/microfrontends package violates the rules by\n // using eval.\n const rawMfConfig = parse(readFileSync(path, 'utf-8')) as Config;\n return new MicrofrontendConfigIsomorphic({\n config: rawMfConfig,\n });\n}\n\nexport function getAllChildApplicationNames(\n mfConfig: MicrofrontendConfigIsomorphic,\n): string[] {\n return mfConfig.getChildApplications().map((app) => app.name);\n}\n\nexport function getLaunchedPathsForApp(\n mfConfig: MicrofrontendConfigIsomorphic,\n appName: string,\n): string[] {\n const app = mfConfig.getApplication(appName);\n if (app instanceof DefaultApplication) {\n return [];\n }\n\n return [\n `/${app.getAssetPrefix()}/_next/static`,\n ...app.routing\n .filter((group) => !group.flag)\n .flatMap((group) => group.paths.flatMap(expandWildcards)),\n ];\n}\n\nexport function getFlaggedPathsForApp(\n mfConfig: MicrofrontendConfigIsomorphic,\n appName: string,\n): string[] {\n const app = mfConfig.getApplication(appName);\n if (app instanceof DefaultApplication) {\n return [];\n }\n\n return app.routing\n .filter((group) => Boolean(group.flag))\n .flatMap((group) => group.paths.flatMap(expandWildcards));\n}\n\n/**\n * Returns a list of examples for all paths in microfrontends.json.\n */\nexport function getAllMicrofrontendPaths(\n mfConfig: MicrofrontendConfigIsomorphic,\n): string[] {\n return mfConfig.getChildApplications().flatMap((app) => {\n return app.routing.flatMap((group) => group.paths.flatMap(expandWildcards));\n });\n}\n\nfunction urlMatches(\n middlewareConfig: MiddlewareConfig,\n path: string,\n doNotMatchWithHasOrMissing?: boolean,\n): boolean {\n if (!middlewareConfig.matcher) {\n return false;\n }\n // This is based off\n // https://github.com/vercel/next.js/blob/4835be182b88f67f282c30db4278c30fe9e5b483/packages/next/src/build/analysis/get-page-static-info.ts#L324\n const matchers = Array.isArray(middlewareConfig.matcher)\n ? middlewareConfig.matcher\n : [middlewareConfig.matcher];\n for (let matcher of matchers) {\n matcher = typeof matcher === 'string' ? { source: matcher } : matcher;\n if (match(matcher.source)(path)) {\n if (doNotMatchWithHasOrMissing && (matcher.has || matcher.missing)) {\n return false;\n }\n return true;\n }\n }\n return false;\n}\n\n/**\n * A test to ensure that middleware is configured to work correctly with\n * microfrontends. Passing this test does NOT guarantee middleware is set up\n * correctly, but this should find many common problems. This should only be run\n * on the application marked as \"default\" in the microfrontend config. If a\n * configuration issue is found, this will throw an exception (this ensures it\n * works with any test framework).\n *\n * For example, if a microfrontend is configured to serve \"/my/path\" then the\n * default application should not contain any matcher that matches \"/my/path\".\n *\n * See [documentation](https://vercel.com/docs/microfrontends/troubleshooting#validatemiddlewareconfig) for more information.\n *\n * @example\n * ```ts\n * test('matches microfrontends paths', () => {\n * expect(() =>\n * validateMiddlewareConfig(config, './microfrontends.json'),\n * ).not.toThrow();\n * });\n * ```\n */\nexport function validateMiddlewareConfig(\n middlewareConfig: MiddlewareConfig,\n microfrontendConfigOrPath: string | MicrofrontendConfigIsomorphic,\n extraProductionMatches?: string[],\n): void {\n const microfrontendConfig =\n typeof microfrontendConfigOrPath === 'string'\n ? loadMicrofrontendConfigForEdge(microfrontendConfigOrPath)\n : microfrontendConfigOrPath;\n\n const errors: string[] = [];\n const usedExtraProductionMatches = new Set<string>();\n\n const wellKnownEndpoint = '/.well-known/vercel/microfrontends/client-config';\n if (!urlMatches(middlewareConfig, wellKnownEndpoint)) {\n errors.push(\n `Middleware must be configured to match ${wellKnownEndpoint}. This path is used by the client to know which flagged paths are routed to which microfrontend based on the flag values for the session. See https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher for more information.`,\n );\n }\n\n for (const application of microfrontendConfig.getChildApplications()) {\n const matches = [...application.routing];\n matches.push({\n paths: [`/${application.getAssetPrefix()}/_next/:path+`],\n });\n\n for (const aMatch of matches) {\n const isFlagged = Boolean(aMatch.flag);\n\n for (const path of aMatch.paths) {\n const pathsToTest = expandWildcards(path);\n for (const testPath of pathsToTest) {\n const pathForDisplay = `${testPath}${path === testPath ? '' : ` (synthesized from ${path})`}`;\n\n const productionUrlMatches = urlMatches(middlewareConfig, testPath);\n if (isFlagged) {\n if (!urlMatches(middlewareConfig, testPath, true)) {\n errors.push(\n `Middleware should be configured to match ${pathForDisplay}. Middleware config matchers for flagged paths should ALWAYS match.`,\n );\n // Skip the remaining expanded wildcard paths (if there are any)\n // to only report a single error per wildcard.\n break;\n }\n } else if (productionUrlMatches) {\n if (extraProductionMatches?.includes(path)) {\n usedExtraProductionMatches.add(path);\n } else {\n errors.push(\n `Middleware should not match ${pathForDisplay}. This path is routed to a microfrontend and will never reach the middleware for the default application.`,\n );\n }\n // Skip the remaining expanded wildcard paths (if there are any)\n // to only report a single error per wildcard.\n break;\n }\n }\n }\n }\n }\n\n const unusedExtraProductionMatches = extraProductionMatches?.filter(\n (x) => !usedExtraProductionMatches.has(x),\n );\n if (unusedExtraProductionMatches?.length) {\n errors.push(\n `The following paths were passed to the extraProductionMatches parameter but were unused. You probably want to remove them from the extraProductionMatches parameter: ${unusedExtraProductionMatches.join(', ')}`,\n );\n }\n\n if (errors.length > 0) {\n const message = `Found the following inconsistencies between your microfrontend config ${\n typeof microfrontendConfigOrPath === 'string'\n ? `(at ${microfrontendConfigOrPath}) `\n : ''\n }and middleware config:\\n\\n- `;\n throw new Error(message + errors.join('\\n\\n- '));\n }\n}\n\n/**\n * Ensures that middleware rewrites to the correct path for flagged paths.\n * IMPORTANT: you must enable the necessary flags before calling this function.\n *\n * See [documentation](https://vercel.com/docs/microfrontends/troubleshooting#validatemiddlewareonflaggedpaths) for more information.\n *\n * @example\n * ```ts\n * jest.mock('flags/next', () => ({\n * flag: jest.fn().mockReturnValue(jest.fn().mockResolvedValue(true)),\n * }));\n *\n * test('matches microfrontends paths', () => {\n * await expect(\n * validateMiddlewareOnFlaggedPaths('./microfrontends.json', middleware),\n * ).resolves.not.toThrow();\n * });\n * ```\n */\nexport async function validateMiddlewareOnFlaggedPaths(\n microfrontendConfigOrPath: string | MicrofrontendConfigIsomorphic,\n middleware: (\n request: NextRequest,\n event: NextFetchEvent,\n ) => Promise<Response | undefined>,\n): Promise<void> {\n const initialEnv = process.env.VERCEL_ENV;\n const initialMfePreviewDomains = process.env.MFE_PREVIEW_DOMAINS;\n try {\n const microfrontendConfig =\n typeof microfrontendConfigOrPath === 'string'\n ? loadMicrofrontendConfigForEdge(microfrontendConfigOrPath)\n : microfrontendConfigOrPath;\n const allAppNames = getAllChildApplicationNames(microfrontendConfig);\n\n const errors: string[] = [];\n for (const appName of allAppNames) {\n const flaggedPaths = getFlaggedPathsForApp(microfrontendConfig, appName);\n if (flaggedPaths.length) {\n for (const path of flaggedPaths) {\n const host =\n microfrontendConfig.defaultApplication.fallback.toString();\n const requestPath = `${host}${path}`;\n const request = new NextRequest(requestPath);\n\n // eslint-disable-next-line no-await-in-loop\n const response = await middleware(\n request,\n {} as unknown as NextFetchEvent,\n );\n const routedZone = response?.headers.get(\n 'x-middleware-request-x-vercel-mfe-zone',\n );\n if (!response) {\n errors.push(\n `middleware did not action for ${requestPath}. Expected to route to ${appName}`,\n );\n } else if (response.status !== 200) {\n errors.push(\n `expected 200 status for ${requestPath} but got ${response.status}`,\n );\n } else if (routedZone !== appName) {\n errors.push(\n `expected ${requestPath} to route to ${appName}, but got ${routedZone}`,\n );\n }\n }\n }\n }\n if (errors.length) {\n throw new Error(errors.join('\\n'));\n }\n } finally {\n process.env.VERCEL_ENV = initialEnv;\n process.env.MFE_PREVIEW_DOMAINS = initialMfePreviewDomains;\n }\n}\n\n/**\n * Validates that the given paths route to the correct microfrontend.\n * The `routesToTest` parameter is a record mapping the application name\n * to a list a paths (with an optional flag) that should be routed to that\n * application. If an issue is found, this will throw an exception so that\n * it can be used with any test framework.\n *\n * See [documentation](https://vercel.com/docs/microfrontends/troubleshooting#validaterouting) for more information.\n *\n * For example:\n *\n * ```ts\n * {\n * 'microfrontend-a': ['/a/path', '/a/longer/path'],\n * 'microfrontend-b': ['/b/path'],\n * 'microfrontend-c': [\n * '/c/path',\n * {\n * 'path': '/c/flagged',\n * 'flag': 'my-flag',\n * }\n * ],\n * }\n * ```\n *\n * This ensures:\n * - `/a/path` and `/a/longer/path` get routed to `microfrontend-a`\n * - `/b/path` gets routed to `microfrontend-b`\n * - `/c/flagged` gets routed to `microfrontend-c` if `my-flag` is enabled.\n */\nexport function validateRouting(\n microfrontendConfigOrPath: string | MicrofrontendConfigIsomorphic,\n routesToTest: Record<string, (string | { path: string; flag: string })[]>,\n) {\n const microfrontendConfig =\n typeof microfrontendConfigOrPath === 'string'\n ? loadMicrofrontendConfigForEdge(microfrontendConfigOrPath)\n : microfrontendConfigOrPath;\n const matches = new Map<{ path: string; flag?: string }, string>();\n for (const application of microfrontendConfig.getChildApplications()) {\n for (const route of application.routing) {\n for (const path of route.paths) {\n matches.set({ path, flag: route.flag }, application.name);\n }\n }\n }\n const errors = [];\n for (const [applicationName, paths] of Object.entries(routesToTest)) {\n if (!microfrontendConfig.hasApplication(applicationName)) {\n errors.push(\n `Application ${applicationName} does not exist in the microfrontends config. The applications in the config are: ${microfrontendConfig\n .getAllApplications()\n .map((app) => app.name)\n .join(', ')}`,\n );\n continue;\n }\n for (const expected of paths) {\n const path = typeof expected === 'string' ? expected : expected.path;\n const flag = typeof expected === 'string' ? undefined : expected.flag;\n const matchedApplications = new Map<string, string[]>();\n const matchesWithoutFlags = new Map<string, string>();\n\n for (const [matcher, applicationMatched] of matches.entries()) {\n if (pathToRegexp(matcher.path).test(path)) {\n if (!matcher.flag || matcher.flag === flag) {\n const existingMatches =\n matchedApplications.get(applicationMatched) ?? [];\n existingMatches.push(matcher.path);\n matchedApplications.set(applicationMatched, existingMatches);\n } else {\n // This path would've matched this application if this flag was set.\n matchesWithoutFlags.set(applicationName, matcher.flag);\n }\n }\n }\n if (matchedApplications.size === 0) {\n matchedApplications.set(\n microfrontendConfig.getDefaultApplication().name,\n ['fallback to default application'],\n );\n }\n if (matchedApplications.size > 1) {\n const formattedMatches = Array.from(\n matchedApplications\n .entries()\n .map(\n ([matchedApplication, matchers]) =>\n `${matchedApplication} (on ${matchers.join(', ')})`,\n ),\n ).join(', ');\n errors.push(\n `${path} can only match one application, but it matched multiple: ${formattedMatches}`,\n );\n } else if (!matchedApplications.has(applicationName)) {\n const actualMatch = matchedApplications.entries().next().value;\n if (!actualMatch) {\n throw new Error(\"this shouldn't happen\");\n }\n const [matchedApplication, matchers] = actualMatch;\n let extraMessage = '';\n if (matchesWithoutFlags.has(applicationName)) {\n const flagToSet = matchesWithoutFlags.get(applicationName);\n extraMessage = ` It would've matched ${applicationName} if the ${flagToSet} flag was set. If this is what you want, replace ${path} in the paths-to-test list with {path: '${path}', flag: '${flagToSet}'}.`;\n }\n errors.push(\n `Expected ${path}${flag ? ` (with flag ${flag})` : ''} to match ${applicationName}, but it matched ${matchedApplication} (on ${matchers.join(', ')}).${extraMessage}`,\n );\n }\n }\n }\n if (errors.length) {\n throw new Error(\n `Incorrect microfrontends routing detected:\\n\\n- ${errors.join('\\n- ')}`,\n );\n }\n}\n","import { parse } from 'jsonc-parser';\nimport { getConfigStringFromEnv } from '../utils/get-config-from-env';\nimport { isDefaultApp } from '../../schema/utils/is-default-app';\nimport type { Config } from '../../schema/types';\nimport { MicrofrontendError } from '../../errors';\nimport { type OverridesConfig, parseOverrides } from '../../overrides';\nimport type { ClientConfig } from '../client/types';\nimport { MicrofrontendConfigClient } from '../client';\nimport { DefaultApplication, ChildApplication } from './application';\nimport { DEFAULT_LOCAL_PROXY_PORT } from './constants';\nimport {\n validateConfigDefaultApplication,\n validateConfigPaths,\n} from './validation';\nimport { hashApplicationName } from './utils/hash-application-name';\n\n/**\n * A class to manage the microfrontends configuration.\n */\nexport class MicrofrontendConfigIsomorphic {\n config: Config;\n defaultApplication: DefaultApplication;\n childApplications: Record<string, ChildApplication> = {};\n overrides?: OverridesConfig;\n options?: Config['options'];\n\n private readonly serialized: {\n config: Config;\n overrides?: OverridesConfig;\n };\n\n constructor({\n config,\n overrides,\n }: {\n config: Config;\n overrides?: OverridesConfig;\n }) {\n // run validation on init\n MicrofrontendConfigIsomorphic.validate(config);\n\n const disableOverrides = config.options?.disableOverrides ?? false;\n this.overrides = overrides && !disableOverrides ? overrides : undefined;\n\n let defaultApplication: DefaultApplication | undefined;\n // create applications\n for (const [appId, appConfig] of Object.entries(config.applications)) {\n const appOverrides = !disableOverrides\n ? this.overrides?.applications[appId]\n : undefined;\n\n if (isDefaultApp(appConfig)) {\n defaultApplication = new DefaultApplication(appId, {\n app: appConfig,\n overrides: appOverrides,\n });\n } else {\n this.childApplications[appId] = new ChildApplication(appId, {\n app: appConfig,\n overrides: appOverrides,\n });\n }\n }\n\n // validate that this.defaultApplication is defined\n if (!defaultApplication) {\n throw new MicrofrontendError(\n 'Could not find default application in microfrontends configuration',\n {\n type: 'application',\n subtype: 'not_found',\n },\n );\n }\n this.defaultApplication = defaultApplication;\n\n this.config = config;\n this.options = config.options;\n this.serialized = {\n config,\n overrides,\n };\n }\n\n static validate(config: string | Config): Config {\n // let this throw if it's not valid JSON\n const c = typeof config === 'string' ? (parse(config) as Config) : config;\n\n validateConfigPaths(c.applications);\n validateConfigDefaultApplication(c.applications);\n\n return c;\n }\n\n static fromEnv({\n cookies,\n }: {\n cookies?: { name: string; value: string }[];\n }): MicrofrontendConfigIsomorphic {\n return new MicrofrontendConfigIsomorphic({\n config: parse(getConfigStringFromEnv()) as Config,\n overrides: parseOverrides(cookies ?? []),\n });\n }\n\n isOverridesDisabled(): boolean {\n return this.options?.disableOverrides ?? false;\n }\n\n getConfig(): Config {\n return this.config;\n }\n\n getApplicationsByType(): {\n defaultApplication?: DefaultApplication;\n applications: ChildApplication[];\n } {\n return {\n defaultApplication: this.defaultApplication,\n applications: Object.values(this.childApplications),\n };\n }\n\n getChildApplications(): ChildApplication[] {\n return Object.values(this.childApplications);\n }\n\n getAllApplications(): (DefaultApplication | ChildApplication)[] {\n return [\n this.defaultApplication,\n ...Object.values(this.childApplications),\n ].filter(Boolean);\n }\n\n getApplication(name: string): DefaultApplication | ChildApplication {\n // check the default\n if (\n this.defaultApplication.name === name ||\n this.defaultApplication.packageName === name\n ) {\n return this.defaultApplication;\n }\n const app =\n this.childApplications[name] ||\n Object.values(this.childApplications).find(\n (child) => child.packageName === name,\n );\n if (!app) {\n throw new MicrofrontendError(\n `Could not find microfrontends configuration for application \"${name}\". If the name in package.json 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 {\n type: 'application',\n subtype: 'not_found',\n },\n );\n }\n\n return app;\n }\n\n hasApplication(name: string): boolean {\n try {\n this.getApplication(name);\n return true;\n } catch {\n return false;\n }\n }\n\n getApplicationByProjectName(\n projectName: string,\n ): DefaultApplication | ChildApplication | undefined {\n // check the default\n if (this.defaultApplication.name === projectName) {\n return this.defaultApplication;\n }\n\n return Object.values(this.childApplications).find(\n (app) => app.name === projectName,\n );\n }\n\n /**\n * Returns the default application.\n */\n getDefaultApplication(): DefaultApplication {\n return this.defaultApplication;\n }\n\n /**\n * Returns the configured port for the local proxy\n */\n getLocalProxyPort(): number {\n return this.config.options?.localProxyPort ?? DEFAULT_LOCAL_PROXY_PORT;\n }\n\n toClientConfig(options?: {\n removeFlaggedPaths?: boolean;\n }): MicrofrontendConfigClient {\n const applications: ClientConfig['applications'] = Object.fromEntries(\n Object.entries(this.childApplications).map(([name, application]) => [\n hashApplicationName(name),\n {\n default: false,\n routing: application.routing,\n },\n ]),\n );\n\n applications[hashApplicationName(this.defaultApplication.name)] = {\n default: true,\n };\n\n return new MicrofrontendConfigClient(\n {\n applications,\n },\n {\n removeFlaggedPaths: options?.removeFlaggedPaths,\n },\n );\n }\n\n /**\n * Serializes the class back to the Schema type.\n *\n * NOTE: This is used when writing the config to disk and must always match the input Schema\n */\n toSchemaJson(): Config {\n return this.serialized.config;\n }\n\n serialize(): {\n config: Config;\n overrides?: OverridesConfig;\n } {\n return this.serialized;\n }\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","import { MicrofrontendError } from '../../errors';\n\n/**\n * Utility to fetch the microfrontend configuration string from the environment.\n */\nexport function getConfigStringFromEnv(): string {\n const config = process.env.MFE_CONFIG;\n if (!config) {\n throw new MicrofrontendError(`Missing \"MFE_CONFIG\" in environment.`, {\n type: 'config',\n subtype: 'not_found_in_env',\n });\n }\n return config;\n}\n","import type { Application, DefaultApplication } from '../types';\n\nexport function isDefaultApp(a: Application): a is DefaultApplication {\n return !('routing' in a);\n}\n","// cookie name needs to match proxy\n// https://github.com/vercel/proxy/blob/fb00d723136ad539a194e4a851dd272010527c35/lib/routing/micro_frontends_overrides.lua#L7\nexport const OVERRIDES_COOKIE_PREFIX = 'vercel-micro-frontends-override';\nexport const OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;\n","import { OVERRIDES_COOKIE_PREFIX } from './constants';\n\nexport function isOverrideCookie(cookie: { name?: string }): boolean {\n return Boolean(cookie.name?.startsWith(OVERRIDES_COOKIE_PREFIX));\n}\n","import { isOverrideCookie } from './is-override-cookie';\nimport { OVERRIDES_ENV_COOKIE_PREFIX } from './constants';\n\nexport function getOverrideFromCookie(cookie: {\n name: string;\n value?: string | null;\n}): { application: string; host: string } | undefined {\n if (!isOverrideCookie(cookie) || !cookie.value) return;\n return {\n application: cookie.name.replace(OVERRIDES_ENV_COOKIE_PREFIX, ''),\n host: cookie.value,\n };\n}\n","import type { OverridesConfig } from './types';\nimport { getOverrideFromCookie } from './get-override-from-cookie';\n\nexport function parseOverrides(\n cookies: { name: string; value?: string | null }[],\n): OverridesConfig {\n const overridesConfig: OverridesConfig = { applications: {} };\n\n cookies.forEach((cookie) => {\n const override = getOverrideFromCookie(cookie);\n if (!override) return;\n overridesConfig.applications[override.application] = {\n environment: { host: override.host },\n };\n });\n\n return overridesConfig;\n}\n","import { pathToRegexp } from 'path-to-regexp';\nimport type { ClientConfig } from './types';\n\nexport interface MicrofrontendConfigClientOptions {\n removeFlaggedPaths?: boolean;\n}\n\nconst regexpCache = new Map<string, RegExp>();\nconst getRegexp = (path: string): RegExp => {\n const existing = regexpCache.get(path);\n if (existing) {\n return existing;\n }\n\n const regexp = pathToRegexp(path);\n regexpCache.set(path, regexp);\n return regexp;\n};\n\nexport class MicrofrontendConfigClient {\n applications: ClientConfig['applications'];\n hasFlaggedPaths: boolean;\n pathCache: Record<string, string> = {};\n private readonly serialized: ClientConfig;\n\n constructor(config: ClientConfig, opts?: MicrofrontendConfigClientOptions) {\n this.hasFlaggedPaths = config.hasFlaggedPaths ?? false;\n for (const app of Object.values(config.applications)) {\n if (app.routing) {\n if (app.routing.some((match) => match.flag)) {\n this.hasFlaggedPaths = true;\n }\n const newRouting = [];\n const pathsWithoutFlags = [];\n for (const group of app.routing) {\n if (group.flag) {\n if (opts?.removeFlaggedPaths) {\n continue;\n }\n if (group.group) {\n delete group.group;\n }\n newRouting.push(group);\n } else {\n pathsWithoutFlags.push(...group.paths);\n }\n }\n if (pathsWithoutFlags.length > 0) {\n newRouting.push({ paths: pathsWithoutFlags });\n }\n app.routing = newRouting;\n }\n }\n this.serialized = config;\n if (this.hasFlaggedPaths) {\n this.serialized.hasFlaggedPaths = this.hasFlaggedPaths;\n }\n this.applications = config.applications;\n }\n\n /**\n * Create a new `MicrofrontendConfigClient` from a JSON string.\n * Config must be passed in to remain framework agnostic\n */\n static fromEnv(config: string | undefined): MicrofrontendConfigClient {\n if (!config) {\n throw new Error(\n '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',\n );\n }\n return new MicrofrontendConfigClient(JSON.parse(config) as ClientConfig);\n }\n\n isEqual(other: MicrofrontendConfigClient): boolean {\n return (\n this === other ||\n JSON.stringify(this.applications) === JSON.stringify(other.applications)\n );\n }\n\n getApplicationNameForPath(path: string): string | null {\n if (!path.startsWith('/')) {\n throw new Error(`Path must start with a /`);\n }\n\n if (this.pathCache[path]) {\n return this.pathCache[path];\n }\n\n const pathname = new URL(path, 'https://example.com').pathname;\n for (const [name, application] of Object.entries(this.applications)) {\n if (application.routing) {\n for (const group of application.routing) {\n for (const childPath of group.paths) {\n const regexp = getRegexp(childPath);\n if (regexp.test(pathname)) {\n this.pathCache[path] = name;\n return name;\n }\n }\n }\n }\n }\n const defaultApplication = Object.entries(this.applications).find(\n ([, application]) => application.default,\n );\n if (!defaultApplication) {\n return null;\n }\n\n this.pathCache[path] = defaultApplication[0];\n return defaultApplication[0];\n }\n\n serialize(): ClientConfig {\n return this.serialized;\n }\n}\n","import { pathToRegexp, parse as parsePathRegexp } from 'path-to-regexp';\nimport type {\n ApplicationId,\n PathGroup,\n ApplicationRouting,\n ChildApplication as ChildApplicationConfig,\n} from '../../schema/types';\nimport { MicrofrontendError } from '../../errors';\nimport { isDefaultApp } from '../../schema/utils/is-default-app';\n\nconst LIST_FORMATTER = new Intl.ListFormat('en', {\n style: 'long',\n type: 'conjunction',\n});\n\nconst VALID_ASSET_PREFIX_REGEXP = /^[a-z](?:[a-z0-9-]*[a-z0-9])?$/;\n\n/**\n * Validate all paths in a configuration - ensures paths do not overlap\n */\nexport const validateConfigPaths = (\n applicationConfigsById?: ApplicationRouting,\n): void => {\n if (!applicationConfigsById) {\n return;\n }\n\n const pathsByApplicationId = new Map<\n PathGroup['paths'][number],\n {\n applications: ApplicationId[];\n matcher: RegExp;\n applicationId?: ApplicationId;\n }\n >();\n const errors: string[] = [];\n\n for (const [id, app] of Object.entries(applicationConfigsById)) {\n if (isDefaultApp(app)) {\n // default applications do not have routing\n continue;\n }\n\n for (const pathMatch of app.routing) {\n for (const path of pathMatch.paths) {\n const maybeError = validatePathExpression(path);\n if (maybeError) {\n errors.push(maybeError);\n } else {\n const existing = pathsByApplicationId.get(path);\n if (existing) {\n existing.applications.push(id);\n } else {\n pathsByApplicationId.set(path, {\n applications: [id],\n matcher: pathToRegexp(path),\n applicationId: id,\n });\n }\n }\n }\n }\n }\n const entries = Array.from(pathsByApplicationId.entries());\n\n for (const [path, { applications: ids, matcher, applicationId }] of entries) {\n if (ids.length > 1) {\n errors.push(\n `Duplicate path \"${path}\" for applications \"${ids.join(', ')}\"`,\n );\n }\n\n for (const [\n matchPath,\n { applications: matchIds, applicationId: matchApplicationId },\n ] of entries) {\n if (path === matchPath) {\n // we're comparing to ourselves, so skip\n continue;\n }\n\n if (applicationId === matchApplicationId) {\n // we're comparing to paths within our own application, which are allowed to overlap, so skip\n continue;\n }\n\n if (matcher.test(matchPath)) {\n const source = `\"${path}\" of application${ids.length > 0 ? 's' : ''} ${ids.join(', ')}`;\n const destination = `\"${matchPath}\" of application${matchIds.length > 0 ? 's' : ''} ${matchIds.join(', ')}`;\n\n errors.push(\n `Overlapping path detected between ${source} and ${destination}`,\n );\n }\n }\n }\n\n if (errors.length) {\n throw new MicrofrontendError(\n `Invalid paths: ${errors.join(', ')}. See supported paths in the documentation https://vercel.com/docs/microfrontends/path-routing#supported-path-expressions.`,\n {\n type: 'config',\n subtype: 'conflicting_paths',\n },\n );\n }\n};\n\n// From https://github.com/pillarjs/path-to-regexp/blob/b0778f5e8e6c6e9ee4e2f5b34e877cc5229f8036/src/index.ts#L143\nconst PATH_DEFAULT_PATTERN = '[^\\\\/#\\\\?]+?';\n\nfunction validatePathExpression(path: string): string | undefined {\n try {\n const tokens = parsePathRegexp(path);\n if (/(?<!\\\\)\\{/.test(path)) {\n return `Optional paths are not supported: ${path}`;\n }\n if (/(?<!\\\\|\\()\\?/.test(path)) {\n return `Optional paths are not supported: ${path}`;\n }\n if (/\\/[^/]*(?<!\\\\):[^/]*(?<!\\\\):[^/]*/.test(path)) {\n return `Only one wildcard is allowed per path segment: ${path}`;\n }\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n if (token === undefined) {\n return `token ${i} in ${path} is undefined, this shouldn't happen`;\n }\n if (typeof token !== 'string') {\n if (!token.name) {\n return `Only named wildcards are allowed: ${path} (hint: add \":path\" to the wildcard)`;\n }\n if (\n token.pattern !== PATH_DEFAULT_PATTERN &&\n // Allows (a|b|c) and ((?!a|b|c).*) regex\n // Only limited regex is supported for now, due to performance considerations\n // Allows all letters, numbers, and hyphens. Other characters must be escaped.\n !/^(?<allowed>[\\w-~]+(?:\\|[^:|()]+)+)$|^\\(\\?!(?<disallowed>[\\w-~]+(?:\\|[^:|()]+)*)\\)\\.\\*$/.test(\n token.pattern.replace(/\\\\./g, ''),\n )\n ) {\n return `Path ${path} cannot use unsupported regular expression wildcard. If the path includes special characters, they must be escaped with backslash (e.g. '\\\\(')`;\n }\n if (token.modifier && i !== tokens.length - 1) {\n return `Modifier ${token.modifier} is not allowed on wildcard :${token.name} in ${path}. Modifiers are only allowed in the last path component`;\n }\n }\n }\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return `Path ${path} could not be parsed into regexp: ${message}`;\n }\n return undefined;\n}\n\n/**\n * Validate all paths in an application - ensures paths are the correct format\n */\nexport const validateAppPaths = (\n name: string,\n app: ChildApplicationConfig,\n): void => {\n // validate routes\n for (const group of app.routing) {\n for (const p of group.paths) {\n if (p === '/') {\n continue;\n }\n if (p.endsWith('/')) {\n throw new MicrofrontendError(\n `Invalid path for application \"${name}\". ${p} must not end with a slash.`,\n { type: 'application', subtype: 'invalid_path' },\n );\n }\n\n if (!p.startsWith('/')) {\n throw new MicrofrontendError(\n `Invalid path for application \"${name}\". ${p} must start with a slash.`,\n { type: 'application', subtype: 'invalid_path' },\n );\n }\n }\n }\n if (app.assetPrefix) {\n if (!VALID_ASSET_PREFIX_REGEXP.test(app.assetPrefix)) {\n throw new MicrofrontendError(\n `Invalid asset prefix for application \"${name}\". ${app.assetPrefix} must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`,\n { type: 'application', subtype: 'invalid_asset_prefix' },\n );\n }\n if (\n app.assetPrefix !== `vc-ap-${name}` &&\n !app.routing.some(\n (group) =>\n group.paths.includes(`/${app.assetPrefix}/:path*`) && !group.flag,\n )\n ) {\n throw new MicrofrontendError(\n `When \\`assetPrefix\\` is specified, \\`/${app.assetPrefix}/:path*\\` must be added the routing paths for the application. Changing the asset prefix is not a forwards and backwards compatible change, and the custom asset prefix should be added to \\`paths\\` and deployed before setting the \\`assetPrefix\\` field.`,\n { type: 'application', subtype: 'invalid_asset_prefix' },\n );\n }\n }\n};\n\n/**\n * Make sure only one `Application` defines routing\n * */\nexport const validateConfigDefaultApplication = (\n applicationConfigsById?: ApplicationRouting,\n): void => {\n if (!applicationConfigsById) {\n return;\n }\n\n const applicationsWithoutRouting = Object.entries(\n applicationConfigsById,\n ).filter(([, app]) => isDefaultApp(app));\n const numApplicationsWithoutRouting = applicationsWithoutRouting.reduce(\n (acc) => {\n return acc + 1;\n },\n 0,\n );\n\n if (numApplicationsWithoutRouting === 0) {\n throw new MicrofrontendError(\n 'No default application found. At least one application needs to be the default by omitting routing.',\n { type: 'config', subtype: 'no_default_application' },\n );\n }\n\n if (numApplicationsWithoutRouting > 1) {\n const applicationNamesMissingRouting = applicationsWithoutRouting.map(\n ([name]) => name,\n );\n throw new MicrofrontendError(\n `All applications except for the default app must contain the \"routing\" field. Applications that are missing routing: ${LIST_FORMATTER.format(applicationNamesMissingRouting)}.`,\n { type: 'config', subtype: 'multiple_default_applications' },\n );\n }\n};\n","import md5 from 'md5';\n\nexport function hashApplicationName(name: string): string {\n if (!name) {\n throw new Error('Application name is required to generate hash');\n }\n\n return md5(name).substring(0, 6).padStart(6, '0');\n}\n","import { hashApplicationName } from './hash-application-name';\n\nconst PREFIX = 'vc-ap';\n\nexport function generateAssetPrefixFromName({\n name,\n}: {\n name: string;\n}): string {\n if (!name) {\n throw new Error('Name is required to generate an asset prefix');\n }\n\n return `${PREFIX}-${hashApplicationName(name)}`;\n}\n","export function generatePortFromName({\n name,\n minPort = 3000,\n maxPort = 8000,\n}: {\n name: string;\n minPort?: number;\n maxPort?: number;\n}): number {\n if (!name) {\n throw new Error('Name is required to generate a port');\n }\n\n // hash the name\n let hash = 0;\n for (let i = 0; i < name.length; i++) {\n // eslint-disable-next-line no-bitwise\n hash = (hash << 5) - hash + name.charCodeAt(i);\n // Convert to 32-bit\n // eslint-disable-next-line no-bitwise\n hash |= 0;\n }\n hash = Math.abs(hash);\n\n // Map the hash to the port range\n const range = maxPort - minPort;\n const port = minPort + (hash % range);\n\n return port;\n}\n","import type {\n HostConfig as RemoteHostConfigSchema,\n LocalHostConfig as LocalHostConfigSchema,\n} from '../../../bin/types';\nimport { generatePortFromName } from './utils/generate-port';\n\ninterface HostOptions {\n isLocal?: boolean;\n}\n\nexport class Host {\n protocol: 'http' | 'https';\n host: string;\n port?: number;\n local: boolean | undefined;\n\n constructor(\n hostConfig: RemoteHostConfigSchema | string,\n options?: HostOptions,\n ) {\n if (typeof hostConfig === 'string') {\n ({\n protocol: this.protocol,\n host: this.host,\n port: this.port,\n } = Host.parseUrl(hostConfig));\n } else {\n const { protocol = 'https', host, port } = hostConfig;\n this.protocol = protocol;\n this.host = host;\n this.port = port;\n }\n this.local = options?.isLocal;\n }\n\n protected static parseUrl(\n url: string,\n defaultProtocol = 'https',\n ): {\n protocol: Host['protocol'];\n host: string;\n port?: number;\n } {\n let hostToParse = url;\n if (!/^https?:\\/\\//.exec(hostToParse)) {\n hostToParse = `${defaultProtocol}://${hostToParse}`;\n }\n const parsed = new URL(hostToParse);\n if (!parsed.hostname) {\n throw new Error(Host.getMicrofrontendsError(url, 'requires a host'));\n }\n if (parsed.hash) {\n throw new Error(\n Host.getMicrofrontendsError(url, 'cannot have a fragment'),\n );\n }\n if (parsed.username || parsed.password) {\n throw new Error(\n Host.getMicrofrontendsError(\n url,\n 'cannot have authentication credentials (username and/or password)',\n ),\n );\n }\n if (parsed.pathname !== '/') {\n throw new Error(Host.getMicrofrontendsError(url, 'cannot have a path'));\n }\n if (parsed.search) {\n throw new Error(\n Host.getMicrofrontendsError(url, 'cannot have query parameters'),\n );\n }\n const protocol = parsed.protocol.slice(0, -1) as Host['protocol'];\n return {\n protocol,\n host: parsed.hostname,\n port: parsed.port ? Number.parseInt(parsed.port) : undefined,\n };\n }\n\n private static getMicrofrontendsError(url: string, message: string): string {\n return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;\n }\n\n isLocal(): boolean {\n return this.local || this.host === 'localhost' || this.host === '127.0.0.1';\n }\n\n toString(): string {\n const url = this.toUrl();\n // strip the trailing slash\n return url.toString().replace(/\\/$/, '');\n }\n\n toUrl(): URL {\n const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ''}`;\n return new URL(url);\n }\n}\n\n/**\n * A Host subclass with defaults for locally running applications\n */\nexport class LocalHost extends Host {\n constructor({\n appName,\n local,\n }: {\n appName: string;\n local?: string | number | LocalHostConfigSchema;\n }) {\n let protocol: RemoteHostConfigSchema['protocol'];\n let host: string | undefined;\n let port: number | undefined;\n if (typeof local === 'number') {\n port = local;\n } else if (typeof local === 'string') {\n if (/^\\d+$/.test(local)) {\n port = Number.parseInt(local);\n } else {\n const parsed = Host.parseUrl(local, 'http');\n protocol = parsed.protocol;\n host = parsed.host;\n port = parsed.port;\n }\n } else if (local) {\n protocol = local.protocol;\n host = local.host;\n port = local.port;\n }\n // set defaults for local\n super({\n protocol: protocol ?? 'http',\n host: host ?? 'localhost',\n port: port ?? generatePortFromName({ name: appName }),\n });\n }\n}\n","export function generateAutomationBypassEnvVarName({\n name,\n}: {\n name: string;\n}): string {\n return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, '_')}`;\n}\n","import type {\n Application as ApplicationConfig,\n DefaultApplication as DefaultApplicationConfig,\n ChildApplication as ChildApplicationConfig,\n PathGroup,\n} from '../../schema/types';\nimport type { ApplicationOverrideConfig } from '../../overrides';\nimport { validateAppPaths } from './validation';\nimport { generateAssetPrefixFromName } from './utils/generate-asset-prefix';\nimport { Host, LocalHost } from './host';\nimport { generateAutomationBypassEnvVarName } from './utils/generate-automation-bypass-env-var-name';\n\nexport class Application {\n readonly default: boolean;\n name: string;\n development: {\n local: LocalHost;\n fallback?: Host;\n };\n fallback?: Host;\n packageName?: string;\n overrides?: {\n environment?: Host;\n };\n readonly serialized: ApplicationConfig;\n\n constructor(\n name: string,\n {\n app,\n overrides,\n isDefault,\n }: {\n app: ApplicationConfig;\n overrides?: ApplicationOverrideConfig;\n isDefault?: boolean;\n },\n ) {\n this.name = name;\n this.development = {\n local: new LocalHost({\n appName: name,\n local: app.development?.local,\n }),\n fallback: app.development?.fallback\n ? new Host(app.development.fallback)\n : undefined,\n };\n if (app.development?.fallback) {\n this.fallback = new Host(app.development.fallback);\n }\n this.packageName = app.packageName;\n this.overrides = overrides?.environment\n ? {\n environment: new Host(overrides.environment),\n }\n : undefined;\n this.default = isDefault ?? false;\n this.serialized = app;\n }\n\n isDefault(): boolean {\n return this.default;\n }\n\n getAssetPrefix(): string {\n const generatedAssetPrefix = generateAssetPrefixFromName({\n name: this.name,\n });\n if ('assetPrefix' in this.serialized) {\n return this.serialized.assetPrefix ?? generatedAssetPrefix;\n }\n return generatedAssetPrefix;\n }\n\n getAutomationBypassEnvVarName(): string {\n return generateAutomationBypassEnvVarName({ name: this.name });\n }\n\n serialize(): ApplicationConfig {\n return this.serialized;\n }\n}\n\nexport class DefaultApplication extends Application {\n readonly default = true;\n fallback: Host;\n\n constructor(\n name: string,\n {\n app,\n overrides,\n }: {\n app: DefaultApplicationConfig;\n overrides?: ApplicationOverrideConfig;\n },\n ) {\n super(name, {\n app,\n overrides,\n isDefault: true,\n });\n\n this.fallback = new Host(app.development.fallback);\n }\n\n getAssetPrefix(): string {\n return '';\n }\n}\n\nexport class ChildApplication extends Application {\n readonly default = false;\n routing: PathGroup[];\n\n constructor(\n name: string,\n {\n app,\n overrides,\n }: {\n app: ChildApplicationConfig;\n overrides?: ApplicationOverrideConfig;\n },\n ) {\n // validate\n ChildApplication.validate(name, app);\n\n super(name, {\n app,\n overrides,\n isDefault: false,\n });\n\n this.routing = app.routing;\n }\n\n static validate(name: string, app: ChildApplicationConfig): void {\n // validate routes\n validateAppPaths(name, app);\n }\n}\n","export const DEFAULT_LOCAL_PROXY_PORT = 3024;\n"],"mappings":"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","names":["pathToRegexp","parse","match","pathToRegexp","pathToRegexp","parse","pathToRegexp"]}
|
package/dist/utils/mfe-port.cjs
CHANGED
|
@@ -225,22 +225,38 @@ var import_node_fs2 = require("fs");
|
|
|
225
225
|
var import_jsonc_parser = require("jsonc-parser");
|
|
226
226
|
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
227
227
|
|
|
228
|
-
// src/config/
|
|
229
|
-
var
|
|
228
|
+
// src/config/microfrontends/utils/get-config-file-name.ts
|
|
229
|
+
var DEFAULT_CONFIGURATION_FILENAMES = [
|
|
230
230
|
"microfrontends.jsonc",
|
|
231
231
|
"microfrontends.json"
|
|
232
232
|
];
|
|
233
|
+
function getPossibleConfigurationFilenames({
|
|
234
|
+
customConfigFilename
|
|
235
|
+
}) {
|
|
236
|
+
if (customConfigFilename) {
|
|
237
|
+
if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
|
|
238
|
+
throw new Error(
|
|
239
|
+
`The VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable must end with '.json' or '.jsonc'. Received: ${customConfigFilename}`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
return Array.from(
|
|
243
|
+
/* @__PURE__ */ new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES])
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
return DEFAULT_CONFIGURATION_FILENAMES;
|
|
247
|
+
}
|
|
233
248
|
|
|
234
249
|
// src/config/microfrontends/utils/infer-microfrontends-location.ts
|
|
235
250
|
var configCache = {};
|
|
236
251
|
function findPackageWithMicrofrontendsConfig({
|
|
237
252
|
repositoryRoot,
|
|
238
|
-
applicationContext
|
|
253
|
+
applicationContext,
|
|
254
|
+
customConfigFilename
|
|
239
255
|
}) {
|
|
240
256
|
const applicationName = applicationContext.name;
|
|
241
257
|
try {
|
|
242
258
|
const microfrontendsJsonPaths = import_fast_glob.default.globSync(
|
|
243
|
-
`**/{${
|
|
259
|
+
`**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
|
|
244
260
|
{
|
|
245
261
|
cwd: repositoryRoot,
|
|
246
262
|
absolute: true,
|
|
@@ -296,6 +312,8 @@ Names of applications in \`microfrontends.json\` must match the Vercel Project n
|
|
|
296
312
|
|
|
297
313
|
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.
|
|
298
314
|
|
|
315
|
+
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.
|
|
316
|
+
|
|
299
317
|
If you suspect this is thrown in error, please reach out to the Vercel team.`,
|
|
300
318
|
{ type: "config", subtype: "inference_failed" }
|
|
301
319
|
);
|
|
@@ -310,7 +328,7 @@ If you suspect this is thrown in error, please reach out to the Vercel team.`,
|
|
|
310
328
|
}
|
|
311
329
|
}
|
|
312
330
|
function inferMicrofrontendsLocation(opts) {
|
|
313
|
-
const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}`;
|
|
331
|
+
const cacheKey = `${opts.repositoryRoot}-${opts.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ""}`;
|
|
314
332
|
if (configCache[cacheKey]) {
|
|
315
333
|
return configCache[cacheKey];
|
|
316
334
|
}
|
|
@@ -376,8 +394,13 @@ function findPackageRoot(startDir) {
|
|
|
376
394
|
// src/config/microfrontends/utils/find-config.ts
|
|
377
395
|
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
378
396
|
var import_node_path5 = require("path");
|
|
379
|
-
function findConfig({
|
|
380
|
-
|
|
397
|
+
function findConfig({
|
|
398
|
+
dir,
|
|
399
|
+
customConfigFilename
|
|
400
|
+
}) {
|
|
401
|
+
for (const filename of getPossibleConfigurationFilenames({
|
|
402
|
+
customConfigFilename
|
|
403
|
+
})) {
|
|
381
404
|
const maybeConfig = (0, import_node_path5.join)(dir, filename);
|
|
382
405
|
if (import_node_fs5.default.existsSync(maybeConfig)) {
|
|
383
406
|
return maybeConfig;
|
|
@@ -444,7 +467,7 @@ var MicrofrontendConfigClient = class {
|
|
|
444
467
|
static fromEnv(config) {
|
|
445
468
|
if (!config) {
|
|
446
469
|
throw new Error(
|
|
447
|
-
"Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
|
|
470
|
+
"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"
|
|
448
471
|
);
|
|
449
472
|
}
|
|
450
473
|
return new MicrofrontendConfigClient(JSON.parse(config));
|
|
@@ -584,10 +607,11 @@ function validatePathExpression(path7) {
|
|
|
584
607
|
}
|
|
585
608
|
if (token.pattern !== PATH_DEFAULT_PATTERN && // Allows (a|b|c) and ((?!a|b|c).*) regex
|
|
586
609
|
// Only limited regex is supported for now, due to performance considerations
|
|
587
|
-
|
|
588
|
-
|
|
610
|
+
// Allows all letters, numbers, and hyphens. Other characters must be escaped.
|
|
611
|
+
!/^(?<allowed>[\w-~]+(?:\|[^:|()]+)+)$|^\(\?!(?<disallowed>[\w-~]+(?:\|[^:|()]+)*)\)\.\*$/.test(
|
|
612
|
+
token.pattern.replace(/\\./g, "")
|
|
589
613
|
)) {
|
|
590
|
-
return `Path ${path7} cannot use unsupported regular expression wildcard`;
|
|
614
|
+
return `Path ${path7} cannot use unsupported regular expression wildcard. If the path includes special characters, they must be escaped with backslash (e.g. '\\(')`;
|
|
591
615
|
}
|
|
592
616
|
if (token.modifier && i !== tokens.length - 1) {
|
|
593
617
|
return `Modifier ${token.modifier} is not allowed on wildcard :${token.name} in ${path7}. Modifiers are only allowed in the last path component`;
|
|
@@ -1479,7 +1503,11 @@ var MicrofrontendsServer = class {
|
|
|
1479
1503
|
appName,
|
|
1480
1504
|
packageRoot
|
|
1481
1505
|
});
|
|
1482
|
-
const
|
|
1506
|
+
const customConfigFilename = process.env.VC_MICROFRONTENDS_CONFIG_FILE_NAME;
|
|
1507
|
+
const maybeConfig = findConfig({
|
|
1508
|
+
dir: packageRoot,
|
|
1509
|
+
customConfigFilename
|
|
1510
|
+
});
|
|
1483
1511
|
if (maybeConfig) {
|
|
1484
1512
|
return MicrofrontendsServer.fromFile({
|
|
1485
1513
|
filePath: maybeConfig,
|
|
@@ -1488,11 +1516,9 @@ var MicrofrontendsServer = class {
|
|
|
1488
1516
|
}
|
|
1489
1517
|
const repositoryRoot = findRepositoryRoot();
|
|
1490
1518
|
const isMonorepo2 = isMonorepo({ repositoryRoot });
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
process.env.VC_MICROFRONTENDS_CONFIG
|
|
1495
|
-
);
|
|
1519
|
+
const configFromEnv = process.env.VC_MICROFRONTENDS_CONFIG;
|
|
1520
|
+
if (typeof configFromEnv === "string") {
|
|
1521
|
+
const maybeConfigFromEnv = (0, import_node_path8.resolve)(packageRoot, configFromEnv);
|
|
1496
1522
|
if (maybeConfigFromEnv) {
|
|
1497
1523
|
return MicrofrontendsServer.fromFile({
|
|
1498
1524
|
filePath: maybeConfigFromEnv,
|
|
@@ -1501,7 +1527,8 @@ var MicrofrontendsServer = class {
|
|
|
1501
1527
|
}
|
|
1502
1528
|
} else {
|
|
1503
1529
|
const maybeConfigFromVercel = findConfig({
|
|
1504
|
-
dir: (0, import_node_path8.join)(packageRoot, ".vercel")
|
|
1530
|
+
dir: (0, import_node_path8.join)(packageRoot, ".vercel"),
|
|
1531
|
+
customConfigFilename
|
|
1505
1532
|
});
|
|
1506
1533
|
if (maybeConfigFromVercel) {
|
|
1507
1534
|
return MicrofrontendsServer.fromFile({
|
|
@@ -1512,9 +1539,13 @@ var MicrofrontendsServer = class {
|
|
|
1512
1539
|
if (isMonorepo2) {
|
|
1513
1540
|
const defaultPackage = inferMicrofrontendsLocation({
|
|
1514
1541
|
repositoryRoot,
|
|
1515
|
-
applicationContext
|
|
1542
|
+
applicationContext,
|
|
1543
|
+
customConfigFilename
|
|
1544
|
+
});
|
|
1545
|
+
const maybeConfigFromDefault = findConfig({
|
|
1546
|
+
dir: defaultPackage,
|
|
1547
|
+
customConfigFilename
|
|
1516
1548
|
});
|
|
1517
|
-
const maybeConfigFromDefault = findConfig({ dir: defaultPackage });
|
|
1518
1549
|
if (maybeConfigFromDefault) {
|
|
1519
1550
|
return MicrofrontendsServer.fromFile({
|
|
1520
1551
|
filePath: maybeConfigFromDefault,
|
|
@@ -1590,19 +1621,19 @@ var MicrofrontendsServer = class {
|
|
|
1590
1621
|
// src/utils/mfe-port.ts
|
|
1591
1622
|
function mfePort(packageDir) {
|
|
1592
1623
|
const { name: appName, version } = getPackageJson(packageDir);
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1624
|
+
try {
|
|
1625
|
+
const result = loadConfig({ packageDir, appName });
|
|
1626
|
+
const { port } = result;
|
|
1627
|
+
return {
|
|
1628
|
+
name: appName,
|
|
1629
|
+
version,
|
|
1630
|
+
port
|
|
1631
|
+
};
|
|
1632
|
+
} catch (e) {
|
|
1633
|
+
throw new Error(`Unable to determine configured port for ${appName}`, {
|
|
1634
|
+
cause: e
|
|
1635
|
+
});
|
|
1599
1636
|
}
|
|
1600
|
-
const { port } = result;
|
|
1601
|
-
return {
|
|
1602
|
-
name: appName,
|
|
1603
|
-
version,
|
|
1604
|
-
port
|
|
1605
|
-
};
|
|
1606
1637
|
}
|
|
1607
1638
|
function getPackageJson(packageDir) {
|
|
1608
1639
|
const filePath = import_node_path9.default.join(packageDir, "package.json");
|
|
@@ -1612,14 +1643,9 @@ function loadConfig({
|
|
|
1612
1643
|
packageDir,
|
|
1613
1644
|
appName
|
|
1614
1645
|
}) {
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
directory: packageDir
|
|
1619
|
-
});
|
|
1620
|
-
} catch (e) {
|
|
1621
|
-
return void 0;
|
|
1622
|
-
}
|
|
1646
|
+
const config = MicrofrontendsServer.infer({
|
|
1647
|
+
directory: packageDir
|
|
1648
|
+
});
|
|
1623
1649
|
const app = config.config.getApplication(appName);
|
|
1624
1650
|
const port = app.development.local.port ?? (app.development.local.protocol === "https" ? 443 : 80);
|
|
1625
1651
|
return { port };
|