@vercel/microfrontends 1.1.1-canary.7 → 1.2.1
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/dist/bin/cli.cjs +50 -17
- package/dist/config.cjs +3 -1
- package/dist/config.cjs.map +1 -1
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/experimental/sveltekit.cjs +18 -14
- package/dist/experimental/sveltekit.cjs.map +1 -1
- package/dist/experimental/sveltekit.js +18 -14
- package/dist/experimental/sveltekit.js.map +1 -1
- package/dist/experimental/vite.cjs +18 -14
- package/dist/experimental/vite.cjs.map +1 -1
- package/dist/experimental/vite.d.ts +3 -2
- package/dist/experimental/vite.js +18 -14
- package/dist/experimental/vite.js.map +1 -1
- package/dist/microfrontends/server.cjs +18 -14
- package/dist/microfrontends/server.cjs.map +1 -1
- package/dist/microfrontends/server.js +18 -14
- package/dist/microfrontends/server.js.map +1 -1
- package/dist/microfrontends/utils.cjs +71 -2
- package/dist/microfrontends/utils.cjs.map +1 -1
- package/dist/microfrontends/utils.d.ts +11 -1
- package/dist/microfrontends/utils.js +69 -1
- 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.js +1 -1
- package/dist/next/client.js.map +1 -1
- package/dist/next/config.cjs +18 -14
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.d.ts +16 -2
- package/dist/next/config.js +18 -14
- package/dist/next/config.js.map +1 -1
- package/dist/next/endpoints.cjs +3 -1
- package/dist/next/endpoints.cjs.map +1 -1
- package/dist/next/endpoints.js +3 -1
- package/dist/next/endpoints.js.map +1 -1
- package/dist/next/middleware.cjs +7 -3
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.js +7 -3
- package/dist/next/middleware.js.map +1 -1
- package/dist/next/testing.cjs +4 -2
- package/dist/next/testing.cjs.map +1 -1
- package/dist/next/testing.d.ts +28 -0
- package/dist/next/testing.js +4 -2
- package/dist/next/testing.js.map +1 -1
- package/dist/utils/mfe-port.cjs +18 -14
- package/dist/utils/mfe-port.cjs.map +1 -1
- package/dist/utils/mfe-port.js +18 -14
- package/dist/utils/mfe-port.js.map +1 -1
- package/package.json +3 -3
package/dist/next/endpoints.cjs
CHANGED
|
@@ -48,7 +48,9 @@ var MicrofrontendConfigClient = class {
|
|
|
48
48
|
*/
|
|
49
49
|
static fromEnv(config, opts) {
|
|
50
50
|
if (!config) {
|
|
51
|
-
throw new Error(
|
|
51
|
+
throw new Error(
|
|
52
|
+
"Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
|
|
53
|
+
);
|
|
52
54
|
}
|
|
53
55
|
return new MicrofrontendConfigClient(
|
|
54
56
|
JSON.parse(config),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/next/endpoints/index.ts","../../src/config/microfrontends-config/client/index.ts","../../src/config/well-known/endpoints.ts"],"sourcesContent":["import type { NextApiResponse } from 'next';\nimport { NextResponse } from 'next/server';\nimport { getWellKnownClientData } from '../../config/well-known/endpoints';\nimport type { WellKnownClientData } from '../../config/well-known/types';\n\n/**\n * A Next.js App Router API handler to export the microfrontends client config\n * data.\n *\n * @example In the `app/.well-known/vercel/microfrontends/client-config/route.ts` file,\n * add this code:\n * ```\n * export { wellKnownNextjsClientConfigAppRoute as GET } from '@vercel/microfrontends/next/endpoints';\n * ```\n */\nexport async function wellKnownNextjsClientConfigAppRoute(\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<NextResponse> {\n return NextResponse.json<WellKnownClientData>(\n await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n ),\n );\n}\n\n/**\n * A Next.js Pages Router API to export the microfrontends client config data to the client.\n *\n * @example In the `pages/api/.well-known/vercel/microfrontends/client-config/index.ts` file,\n * add this code:\n * ```\n * import { handleClientConfigForPagesRouter } from '@vercel/microfrontends/next/endpoints';\n * import type { NextApiResponse } from 'next';\n *\n * async function handler(\n * _,\n * res: NextApiResponse,\n * ): Promise<void> {\n * await handleClientConfigForPagesRouter(res, {\n * flagValue: () => Promise.resolve(true)\n * });\n * }\n * ```\n *\n * Then also make sure to add the following rewrite rule to your `next.config.js` file:\n * ```\n * rewrites: () =>\n * Promise.resolve([\n * {\n * source: '/.well-known/vercel/microfrontends/client-config',\n * destination: '/api/.well-known/vercel/microfrontends/client-config',\n * },\n * ]),\n * ```\n */\nexport async function handleClientConfigForPagesRouter(\n res: NextApiResponse,\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<void> {\n const clientData = await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n );\n res.status(200).json(clientData);\n}\n\nexport { getWellKnownClientData };\nexport type { WellKnownClientData };\n","import { pathToRegexp } from 'path-to-regexp';\nimport type { ClientConfig } from './types';\n\ninterface MicrofrontendConfigClientOptions {\n removeFlaggedPaths?: boolean;\n}\n\nexport class MicrofrontendConfigClient {\n applications: ClientConfig['applications'];\n pathCache: Record<string, string> = {};\n private readonly serialized: ClientConfig;\n\n constructor(config: ClientConfig, opts?: MicrofrontendConfigClientOptions) {\n this.serialized = config;\n if (opts?.removeFlaggedPaths) {\n for (const app of Object.values(config.applications)) {\n if (app.routing) {\n app.routing = app.routing.filter((match) => !match.flag);\n }\n }\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(\n config: string | undefined,\n opts?: MicrofrontendConfigClientOptions,\n ): MicrofrontendConfigClient {\n if (!config) {\n throw new Error('
|
|
1
|
+
{"version":3,"sources":["../../src/next/endpoints/index.ts","../../src/config/microfrontends-config/client/index.ts","../../src/config/well-known/endpoints.ts"],"sourcesContent":["import type { NextApiResponse } from 'next';\nimport { NextResponse } from 'next/server';\nimport { getWellKnownClientData } from '../../config/well-known/endpoints';\nimport type { WellKnownClientData } from '../../config/well-known/types';\n\n/**\n * A Next.js App Router API handler to export the microfrontends client config\n * data.\n *\n * @example In the `app/.well-known/vercel/microfrontends/client-config/route.ts` file,\n * add this code:\n * ```\n * export { wellKnownNextjsClientConfigAppRoute as GET } from '@vercel/microfrontends/next/endpoints';\n * ```\n */\nexport async function wellKnownNextjsClientConfigAppRoute(\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<NextResponse> {\n return NextResponse.json<WellKnownClientData>(\n await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n ),\n );\n}\n\n/**\n * A Next.js Pages Router API to export the microfrontends client config data to the client.\n *\n * @example In the `pages/api/.well-known/vercel/microfrontends/client-config/index.ts` file,\n * add this code:\n * ```\n * import { handleClientConfigForPagesRouter } from '@vercel/microfrontends/next/endpoints';\n * import type { NextApiResponse } from 'next';\n *\n * async function handler(\n * _,\n * res: NextApiResponse,\n * ): Promise<void> {\n * await handleClientConfigForPagesRouter(res, {\n * flagValue: () => Promise.resolve(true)\n * });\n * }\n * ```\n *\n * Then also make sure to add the following rewrite rule to your `next.config.js` file:\n * ```\n * rewrites: () =>\n * Promise.resolve([\n * {\n * source: '/.well-known/vercel/microfrontends/client-config',\n * destination: '/api/.well-known/vercel/microfrontends/client-config',\n * },\n * ]),\n * ```\n */\nexport async function handleClientConfigForPagesRouter(\n res: NextApiResponse,\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<void> {\n const clientData = await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n );\n res.status(200).json(clientData);\n}\n\nexport { getWellKnownClientData };\nexport type { WellKnownClientData };\n","import { pathToRegexp } from 'path-to-regexp';\nimport type { ClientConfig } from './types';\n\ninterface MicrofrontendConfigClientOptions {\n removeFlaggedPaths?: boolean;\n}\n\nexport class MicrofrontendConfigClient {\n applications: ClientConfig['applications'];\n pathCache: Record<string, string> = {};\n private readonly serialized: ClientConfig;\n\n constructor(config: ClientConfig, opts?: MicrofrontendConfigClientOptions) {\n this.serialized = config;\n if (opts?.removeFlaggedPaths) {\n for (const app of Object.values(config.applications)) {\n if (app.routing) {\n app.routing = app.routing.filter((match) => !match.flag);\n }\n }\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(\n config: string | undefined,\n opts?: MicrofrontendConfigClientOptions,\n ): 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(\n JSON.parse(config) as ClientConfig,\n opts,\n );\n }\n\n isEqual(other: MicrofrontendConfigClient): boolean {\n return (\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 = pathToRegexp(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 { MicrofrontendConfigClient } from '../microfrontends-config/client';\nimport type { WellKnownClientData } from './types';\n\n/**\n * Returns data used by the client to ensure that navigations across\n * microfrontend boundaries are routed and prefetched correctly. The client\n * configuration is safe to expose to users.\n *\n * This data should be exposed in a `.well-known/vercel/microfrontends/client-config`\n * endpoint.\n */\nexport async function getWellKnownClientData(\n clientConfig: string | undefined,\n flagValues: Record<string, () => Promise<boolean>> = {},\n): Promise<WellKnownClientData> {\n const config = MicrofrontendConfigClient.fromEnv(clientConfig);\n for (const [applicationName, application] of Object.entries(\n config.applications,\n )) {\n if (!application.routing) {\n continue;\n }\n const newRoutingMatches = [];\n for (const pathGroup of application.routing) {\n if (pathGroup.flag) {\n const flagName = pathGroup.flag;\n const flagFn = flagValues[flagName];\n if (!flagFn) {\n throw new Error(\n `Flag \"${flagName}\" was specified to control routing for path group \"${pathGroup.group}\" in application ${applicationName} but not found in provided flag values.`,\n );\n }\n // eslint-disable-next-line no-await-in-loop\n const flagEnabled = await flagFn();\n if (flagEnabled) {\n newRoutingMatches.push(pathGroup);\n }\n } else {\n newRoutingMatches.push(pathGroup);\n }\n }\n application.routing = newRoutingMatches;\n }\n\n return {\n config: config.serialize(),\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/next/endpoints.js
CHANGED
|
@@ -22,7 +22,9 @@ var MicrofrontendConfigClient = class {
|
|
|
22
22
|
*/
|
|
23
23
|
static fromEnv(config, opts) {
|
|
24
24
|
if (!config) {
|
|
25
|
-
throw new Error(
|
|
25
|
+
throw new Error(
|
|
26
|
+
"Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
|
|
27
|
+
);
|
|
26
28
|
}
|
|
27
29
|
return new MicrofrontendConfigClient(
|
|
28
30
|
JSON.parse(config),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/next/endpoints/index.ts","../../src/config/microfrontends-config/client/index.ts","../../src/config/well-known/endpoints.ts"],"sourcesContent":["import type { NextApiResponse } from 'next';\nimport { NextResponse } from 'next/server';\nimport { getWellKnownClientData } from '../../config/well-known/endpoints';\nimport type { WellKnownClientData } from '../../config/well-known/types';\n\n/**\n * A Next.js App Router API handler to export the microfrontends client config\n * data.\n *\n * @example In the `app/.well-known/vercel/microfrontends/client-config/route.ts` file,\n * add this code:\n * ```\n * export { wellKnownNextjsClientConfigAppRoute as GET } from '@vercel/microfrontends/next/endpoints';\n * ```\n */\nexport async function wellKnownNextjsClientConfigAppRoute(\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<NextResponse> {\n return NextResponse.json<WellKnownClientData>(\n await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n ),\n );\n}\n\n/**\n * A Next.js Pages Router API to export the microfrontends client config data to the client.\n *\n * @example In the `pages/api/.well-known/vercel/microfrontends/client-config/index.ts` file,\n * add this code:\n * ```\n * import { handleClientConfigForPagesRouter } from '@vercel/microfrontends/next/endpoints';\n * import type { NextApiResponse } from 'next';\n *\n * async function handler(\n * _,\n * res: NextApiResponse,\n * ): Promise<void> {\n * await handleClientConfigForPagesRouter(res, {\n * flagValue: () => Promise.resolve(true)\n * });\n * }\n * ```\n *\n * Then also make sure to add the following rewrite rule to your `next.config.js` file:\n * ```\n * rewrites: () =>\n * Promise.resolve([\n * {\n * source: '/.well-known/vercel/microfrontends/client-config',\n * destination: '/api/.well-known/vercel/microfrontends/client-config',\n * },\n * ]),\n * ```\n */\nexport async function handleClientConfigForPagesRouter(\n res: NextApiResponse,\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<void> {\n const clientData = await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n );\n res.status(200).json(clientData);\n}\n\nexport { getWellKnownClientData };\nexport type { WellKnownClientData };\n","import { pathToRegexp } from 'path-to-regexp';\nimport type { ClientConfig } from './types';\n\ninterface MicrofrontendConfigClientOptions {\n removeFlaggedPaths?: boolean;\n}\n\nexport class MicrofrontendConfigClient {\n applications: ClientConfig['applications'];\n pathCache: Record<string, string> = {};\n private readonly serialized: ClientConfig;\n\n constructor(config: ClientConfig, opts?: MicrofrontendConfigClientOptions) {\n this.serialized = config;\n if (opts?.removeFlaggedPaths) {\n for (const app of Object.values(config.applications)) {\n if (app.routing) {\n app.routing = app.routing.filter((match) => !match.flag);\n }\n }\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(\n config: string | undefined,\n opts?: MicrofrontendConfigClientOptions,\n ): MicrofrontendConfigClient {\n if (!config) {\n throw new Error('
|
|
1
|
+
{"version":3,"sources":["../../src/next/endpoints/index.ts","../../src/config/microfrontends-config/client/index.ts","../../src/config/well-known/endpoints.ts"],"sourcesContent":["import type { NextApiResponse } from 'next';\nimport { NextResponse } from 'next/server';\nimport { getWellKnownClientData } from '../../config/well-known/endpoints';\nimport type { WellKnownClientData } from '../../config/well-known/types';\n\n/**\n * A Next.js App Router API handler to export the microfrontends client config\n * data.\n *\n * @example In the `app/.well-known/vercel/microfrontends/client-config/route.ts` file,\n * add this code:\n * ```\n * export { wellKnownNextjsClientConfigAppRoute as GET } from '@vercel/microfrontends/next/endpoints';\n * ```\n */\nexport async function wellKnownNextjsClientConfigAppRoute(\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<NextResponse> {\n return NextResponse.json<WellKnownClientData>(\n await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n ),\n );\n}\n\n/**\n * A Next.js Pages Router API to export the microfrontends client config data to the client.\n *\n * @example In the `pages/api/.well-known/vercel/microfrontends/client-config/index.ts` file,\n * add this code:\n * ```\n * import { handleClientConfigForPagesRouter } from '@vercel/microfrontends/next/endpoints';\n * import type { NextApiResponse } from 'next';\n *\n * async function handler(\n * _,\n * res: NextApiResponse,\n * ): Promise<void> {\n * await handleClientConfigForPagesRouter(res, {\n * flagValue: () => Promise.resolve(true)\n * });\n * }\n * ```\n *\n * Then also make sure to add the following rewrite rule to your `next.config.js` file:\n * ```\n * rewrites: () =>\n * Promise.resolve([\n * {\n * source: '/.well-known/vercel/microfrontends/client-config',\n * destination: '/api/.well-known/vercel/microfrontends/client-config',\n * },\n * ]),\n * ```\n */\nexport async function handleClientConfigForPagesRouter(\n res: NextApiResponse,\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<void> {\n const clientData = await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n );\n res.status(200).json(clientData);\n}\n\nexport { getWellKnownClientData };\nexport type { WellKnownClientData };\n","import { pathToRegexp } from 'path-to-regexp';\nimport type { ClientConfig } from './types';\n\ninterface MicrofrontendConfigClientOptions {\n removeFlaggedPaths?: boolean;\n}\n\nexport class MicrofrontendConfigClient {\n applications: ClientConfig['applications'];\n pathCache: Record<string, string> = {};\n private readonly serialized: ClientConfig;\n\n constructor(config: ClientConfig, opts?: MicrofrontendConfigClientOptions) {\n this.serialized = config;\n if (opts?.removeFlaggedPaths) {\n for (const app of Object.values(config.applications)) {\n if (app.routing) {\n app.routing = app.routing.filter((match) => !match.flag);\n }\n }\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(\n config: string | undefined,\n opts?: MicrofrontendConfigClientOptions,\n ): 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(\n JSON.parse(config) as ClientConfig,\n opts,\n );\n }\n\n isEqual(other: MicrofrontendConfigClient): boolean {\n return (\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 = pathToRegexp(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 { MicrofrontendConfigClient } from '../microfrontends-config/client';\nimport type { WellKnownClientData } from './types';\n\n/**\n * Returns data used by the client to ensure that navigations across\n * microfrontend boundaries are routed and prefetched correctly. The client\n * configuration is safe to expose to users.\n *\n * This data should be exposed in a `.well-known/vercel/microfrontends/client-config`\n * endpoint.\n */\nexport async function getWellKnownClientData(\n clientConfig: string | undefined,\n flagValues: Record<string, () => Promise<boolean>> = {},\n): Promise<WellKnownClientData> {\n const config = MicrofrontendConfigClient.fromEnv(clientConfig);\n for (const [applicationName, application] of Object.entries(\n config.applications,\n )) {\n if (!application.routing) {\n continue;\n }\n const newRoutingMatches = [];\n for (const pathGroup of application.routing) {\n if (pathGroup.flag) {\n const flagName = pathGroup.flag;\n const flagFn = flagValues[flagName];\n if (!flagFn) {\n throw new Error(\n `Flag \"${flagName}\" was specified to control routing for path group \"${pathGroup.group}\" in application ${applicationName} but not found in provided flag values.`,\n );\n }\n // eslint-disable-next-line no-await-in-loop\n const flagEnabled = await flagFn();\n if (flagEnabled) {\n newRoutingMatches.push(pathGroup);\n }\n } else {\n newRoutingMatches.push(pathGroup);\n }\n }\n application.routing = newRoutingMatches;\n }\n\n return {\n config: config.serialize(),\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/next/middleware.cjs
CHANGED
|
@@ -168,7 +168,9 @@ var MicrofrontendConfigClient = class {
|
|
|
168
168
|
*/
|
|
169
169
|
static fromEnv(config, opts) {
|
|
170
170
|
if (!config) {
|
|
171
|
-
throw new Error(
|
|
171
|
+
throw new Error(
|
|
172
|
+
"Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
|
|
173
|
+
);
|
|
172
174
|
}
|
|
173
175
|
return new MicrofrontendConfigClient(
|
|
174
176
|
JSON.parse(config),
|
|
@@ -882,7 +884,9 @@ function getMicrofrontendsMiddleware({
|
|
|
882
884
|
});
|
|
883
885
|
const middlewares = [];
|
|
884
886
|
if (!process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION) {
|
|
885
|
-
throw new Error(
|
|
887
|
+
throw new Error(
|
|
888
|
+
"The NEXT_PUBLIC_MFE_CURRENT_APPLICATION environment variable is not set. Did you run `withMicrofrontends` in your Next.js config?"
|
|
889
|
+
);
|
|
886
890
|
}
|
|
887
891
|
const currentApplication = microfrontends.getApplication(
|
|
888
892
|
process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION
|
|
@@ -898,7 +902,7 @@ function getMicrofrontendsMiddleware({
|
|
|
898
902
|
const flagFn = flagValues?.[flagName];
|
|
899
903
|
if (!flagFn) {
|
|
900
904
|
throw new Error(
|
|
901
|
-
`Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${application.name} but not found in provided flag values.`
|
|
905
|
+
`Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${application.name} but not found in provided flag values. See https://vercel.com/docs/microfrontends/path-routing#add-microfrontends-middleware for more information.`
|
|
902
906
|
);
|
|
903
907
|
}
|
|
904
908
|
for (const path of pathGroup.paths) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/next/middleware/index.ts","../../src/next/middleware/middleware.ts","../../src/next/utils/route-to-local-proxy.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/microfrontends-config/client/index.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/isomorphic/validation.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":["export * from './middleware';\nexport * from './types';\n","/// <reference types=\"@edge-runtime/types\" />\n\nimport type { NextRequest } from 'next/server';\nimport { NextResponse } from 'next/server';\nimport { pathToRegexp } from 'path-to-regexp';\nimport type { ChildApplication } from '../../config/microfrontends-config/isomorphic/application';\nimport { routeToLocalProxy } from '../utils/route-to-local-proxy';\nimport { MicrofrontendConfigIsomorphic } from '../../config/microfrontends-config/isomorphic';\nimport type {\n MicrofrontendsMiddleware,\n MicrofrontendsMiddlewareHandler,\n} from './types';\n\n// Extracts the flag value override if one is present in the headers\nfunction getMfeFlagHeader(req: NextRequest): boolean | null {\n const flagValue = req.headers.get('x-vercel-mfe-flag-value');\n if (flagValue === 'true') {\n return true;\n }\n if (flagValue === 'false') {\n return false;\n }\n return null;\n}\n\ninterface GetFlagHandlerParams {\n application: ChildApplication;\n flagFn: () => Promise<boolean>;\n flagName: string;\n pattern: RegExp;\n localProxyPort: number;\n}\n\nfunction getFlagHandler({\n application,\n flagFn,\n flagName,\n pattern,\n localProxyPort,\n}: GetFlagHandlerParams): MicrofrontendsMiddlewareHandler {\n return async (req: NextRequest): Promise<NextResponse | undefined> => {\n try {\n const pathname = req.nextUrl.pathname;\n\n // If the pattern doesn't match, we don't need to execute the flag\n const flagValueFromHeader = routeToLocalProxy()\n ? getMfeFlagHeader(req)\n : null;\n if (pattern.test(pathname) && (flagValueFromHeader ?? (await flagFn()))) {\n const headers = new Headers(req.headers);\n /**\n * This header informs the proxy which zone the route the request to.\n * It will override any provided redirect / rewrite host.\n *\n * If a rewrite / redirect includes this header, the proxy will perform the\n * action, but will also replace the host with corresponding host for the zone.\n */\n headers.set('x-vercel-mfe-zone', application.name);\n const middlewareResponseInit = {\n request: {\n headers,\n },\n };\n if (routeToLocalProxy()) {\n if (process.env.MFE_DEBUG) {\n // eslint-disable-next-line no-console\n console.log(\n `Routing flagged path \"${pathname}\" to local proxy for application \"${application.name}\"`,\n );\n }\n const url = req.nextUrl;\n url.host = `localhost:${localProxyPort}`;\n return NextResponse.rewrite(url, middlewareResponseInit);\n }\n if (process.env.MFE_DEBUG) {\n // eslint-disable-next-line no-console\n console.log(\n `Routing flagged path \"${pathname}\" to application \"${application.name}\"`,\n );\n }\n return NextResponse.next(middlewareResponseInit);\n }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(\n `An error occured in the microfrontends middleware evaluating the flag \"${flagName}\":`,\n e,\n );\n // still want to throw the error, just also making sure the error is logged\n throw e;\n }\n };\n // If the path does not match the pattern, we don't do anything and let the request continue\n}\n\n/**\n * Returns an array of middleware functions that will handle routing to the\n * right micro-frontends for the provided configuration.\n *\n * @param config - The micro-frontends configuration object.\n * @param flagValues - An object that maps flag names to functions that return the flag value.\n */\nexport function getMicrofrontendsMiddleware({\n request,\n flagValues,\n}: {\n request: NextRequest;\n flagValues?: Record<string, () => Promise<boolean>>;\n}): MicrofrontendsMiddleware[] {\n const microfrontends = MicrofrontendConfigIsomorphic.fromEnv({\n cookies: request.cookies.getAll(),\n });\n const middlewares: MicrofrontendsMiddleware[] = [];\n\n if (!process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION) {\n throw new Error('NEXT_PUBLIC_MFE_CURRENT_APPLICATION is not set');\n }\n\n const currentApplication = microfrontends.getApplication(\n process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION,\n );\n\n if (!currentApplication.isDefault()) {\n return middlewares;\n }\n\n const localProxyPort = microfrontends.getLocalProxyPort();\n\n for (const application of microfrontends.getChildApplications()) {\n for (const pathGroup of application.routing) {\n const flagName = pathGroup.flag;\n if (flagName) {\n const flagFn = flagValues?.[flagName];\n if (!flagFn) {\n throw new Error(\n `Flag \"${flagName}\" was specified to control routing for path group \"${pathGroup.group}\" in application ${application.name} but not found in provided flag values.`,\n );\n }\n for (const path of pathGroup.paths) {\n const pattern = pathToRegexp(path);\n middlewares.push({\n src: pattern,\n fn: getFlagHandler({\n application,\n flagFn,\n flagName,\n pattern,\n localProxyPort,\n }),\n });\n }\n }\n }\n }\n\n return middlewares;\n}\n\n/**\n * Executes the middlewares returned by `getMicrofrontendsMiddleware` and\n * returns a `Response` if any of the micro-frontends middlewares match or\n * `undefined` if none match. If a `Response` object is returned, the calling\n * code should return that Response from the Next.js middleware in order to\n * stop execution of the middleware and perform the rewrite.\n */\nexport async function runMicrofrontendsMiddleware({\n request,\n flagValues,\n}: {\n request: NextRequest;\n flagValues?: Record<string, () => Promise<boolean>>;\n}): Promise<Response | undefined> {\n const pathname = request.nextUrl.pathname;\n const middlewares = getMicrofrontendsMiddleware({\n request,\n flagValues,\n });\n\n for (const mware of middlewares) {\n if (\n typeof mware.src === 'string'\n ? pathname === mware.src\n : mware.src.test(pathname)\n ) {\n // eslint-disable-next-line no-await-in-loop\n const response = await mware.fn(request);\n if (response) {\n return response;\n }\n }\n }\n}\n","export function routeToLocalProxy(): boolean {\n const isDevEnv = (process.env.VERCEL_ENV ?? 'development') === 'development';\n\n return isDevEnv && Boolean(process.env.TURBO_TASK_HAS_MFE_PROXY);\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 type { ClientConfig } from '../client/types';\nimport { MicrofrontendError } from '../../errors';\nimport { MicrofrontendConfigClient } from '../client';\nimport { type OverridesConfig, parseOverrides } from '../../overrides';\nimport { DefaultApplication, ChildApplication } from './application';\nimport { DEFAULT_LOCAL_PROXY_PORT } from './constants';\nimport {\n validateConfigDefaultApplication,\n validateConfigPaths,\n validateDeprecatedFields,\n} from './validation';\n\ninterface ValidationOptions {\n skipValidation?: 'deprecatedFields'[];\n}\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 opts,\n }: {\n config: Config;\n overrides?: OverridesConfig;\n opts?: ValidationOptions;\n }) {\n // run validation on init\n MicrofrontendConfigIsomorphic.validate(config, opts);\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, opts?: ValidationOptions): Config {\n const skipValidation: ValidationOptions['skipValidation'] =\n opts?.skipValidation ?? [];\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 if (!skipValidation.includes('deprecatedFields')) {\n validateDeprecatedFields(c);\n }\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}\"`,\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 getApplicationByProjectId(\n projectId: string,\n ): DefaultApplication | ChildApplication | undefined {\n // check the default\n if (this.defaultApplication.projectId === projectId) {\n return this.defaultApplication;\n }\n\n return Object.values(this.childApplications).find(\n (app) => app.projectId === projectId,\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 /**\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 toClientConfig(): MicrofrontendConfigClient {\n const applications: ClientConfig['applications'] = Object.fromEntries(\n Object.entries(this.childApplications).map(([name, application]) => [\n name,\n {\n default: false,\n routing: application.routing,\n },\n ]),\n );\n\n // add the default application\n applications[this.defaultApplication.name] = {\n default: true,\n };\n\n return new MicrofrontendConfigClient({\n applications,\n });\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","import { pathToRegexp } from 'path-to-regexp';\nimport type { ClientConfig } from './types';\n\ninterface MicrofrontendConfigClientOptions {\n removeFlaggedPaths?: boolean;\n}\n\nexport class MicrofrontendConfigClient {\n applications: ClientConfig['applications'];\n pathCache: Record<string, string> = {};\n private readonly serialized: ClientConfig;\n\n constructor(config: ClientConfig, opts?: MicrofrontendConfigClientOptions) {\n this.serialized = config;\n if (opts?.removeFlaggedPaths) {\n for (const app of Object.values(config.applications)) {\n if (app.routing) {\n app.routing = app.routing.filter((match) => !match.flag);\n }\n }\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(\n config: string | undefined,\n opts?: MicrofrontendConfigClientOptions,\n ): MicrofrontendConfigClient {\n if (!config) {\n throw new Error('No microfrontends configuration found');\n }\n return new MicrofrontendConfigClient(\n JSON.parse(config) as ClientConfig,\n opts,\n );\n }\n\n isEqual(other: MicrofrontendConfigClient): boolean {\n return (\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 = pathToRegexp(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","// 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, parse as parsePathRegexp } from 'path-to-regexp';\nimport type {\n ApplicationId,\n PathGroup,\n ApplicationRouting,\n ChildApplication as ChildApplicationConfig,\n Config,\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\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};\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\n// TODO: Remove this after 4 May 2025 when the new schema has been fully in use for 30 days and thus we can delete the deprecated fields.\nexport const validateDeprecatedFields = (config: Config): void => {\n const errors = [];\n\n for (const [applicationId, application] of Object.entries(\n config.applications,\n )) {\n if (application.development?.localPort) {\n errors.push(\n `Application '${applicationId}' cannot contain deprecated field 'development.localPort'. Use 'developement.local' instead.`,\n );\n }\n if (application.projectId) {\n // This will be an error in the next release\n }\n }\n\n if (errors.length) {\n throw new MicrofrontendError(\n `Microfrontends configuration file errors:\\n- ${errors.join('\\n- ')}`,\n {\n type: 'config',\n subtype: 'depcrecated_field',\n },\n );\n }\n};\n","const 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}-${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 localPort,\n local,\n }: {\n appName: string;\n localPort?: number;\n local?: string | number | LocalHostConfigSchema;\n }) {\n if (localPort && local) {\n throw new Error(\n `Microfrontends configuration error: '${appName}' has both the 'development.local' and 'development.localPort' fields set. Please remove the 'development.localPort' field and ensure the 'development.local' field has the correct port.`,\n );\n }\n let protocol: RemoteHostConfigSchema['protocol'];\n let host: string | undefined;\n let port: number | undefined;\n if (localPort) {\n port = localPort;\n } else 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 projectId?: string;\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 localPort: app.development?.localPort,\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.projectId = app.projectId;\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 return generateAssetPrefixFromName({ name: this.name });\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":["import_path_to_regexp","import_path_to_regexp","parsePathRegexp"]}
|
|
1
|
+
{"version":3,"sources":["../../src/next/middleware/index.ts","../../src/next/middleware/middleware.ts","../../src/next/utils/route-to-local-proxy.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/microfrontends-config/client/index.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/isomorphic/validation.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":["export * from './middleware';\nexport * from './types';\n","/// <reference types=\"@edge-runtime/types\" />\n\nimport type { NextRequest } from 'next/server';\nimport { NextResponse } from 'next/server';\nimport { pathToRegexp } from 'path-to-regexp';\nimport type { ChildApplication } from '../../config/microfrontends-config/isomorphic/application';\nimport { routeToLocalProxy } from '../utils/route-to-local-proxy';\nimport { MicrofrontendConfigIsomorphic } from '../../config/microfrontends-config/isomorphic';\nimport type {\n MicrofrontendsMiddleware,\n MicrofrontendsMiddlewareHandler,\n} from './types';\n\n// Extracts the flag value override if one is present in the headers\nfunction getMfeFlagHeader(req: NextRequest): boolean | null {\n const flagValue = req.headers.get('x-vercel-mfe-flag-value');\n if (flagValue === 'true') {\n return true;\n }\n if (flagValue === 'false') {\n return false;\n }\n return null;\n}\n\ninterface GetFlagHandlerParams {\n application: ChildApplication;\n flagFn: () => Promise<boolean>;\n flagName: string;\n pattern: RegExp;\n localProxyPort: number;\n}\n\nfunction getFlagHandler({\n application,\n flagFn,\n flagName,\n pattern,\n localProxyPort,\n}: GetFlagHandlerParams): MicrofrontendsMiddlewareHandler {\n return async (req: NextRequest): Promise<NextResponse | undefined> => {\n try {\n const pathname = req.nextUrl.pathname;\n\n // If the pattern doesn't match, we don't need to execute the flag\n const flagValueFromHeader = routeToLocalProxy()\n ? getMfeFlagHeader(req)\n : null;\n if (pattern.test(pathname) && (flagValueFromHeader ?? (await flagFn()))) {\n const headers = new Headers(req.headers);\n /**\n * This header informs the proxy which zone the route the request to.\n * It will override any provided redirect / rewrite host.\n *\n * If a rewrite / redirect includes this header, the proxy will perform the\n * action, but will also replace the host with corresponding host for the zone.\n */\n headers.set('x-vercel-mfe-zone', application.name);\n const middlewareResponseInit = {\n request: {\n headers,\n },\n };\n if (routeToLocalProxy()) {\n if (process.env.MFE_DEBUG) {\n // eslint-disable-next-line no-console\n console.log(\n `Routing flagged path \"${pathname}\" to local proxy for application \"${application.name}\"`,\n );\n }\n const url = req.nextUrl;\n url.host = `localhost:${localProxyPort}`;\n return NextResponse.rewrite(url, middlewareResponseInit);\n }\n if (process.env.MFE_DEBUG) {\n // eslint-disable-next-line no-console\n console.log(\n `Routing flagged path \"${pathname}\" to application \"${application.name}\"`,\n );\n }\n return NextResponse.next(middlewareResponseInit);\n }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(\n `An error occured in the microfrontends middleware evaluating the flag \"${flagName}\":`,\n e,\n );\n // still want to throw the error, just also making sure the error is logged\n throw e;\n }\n };\n // If the path does not match the pattern, we don't do anything and let the request continue\n}\n\n/**\n * Returns an array of middleware functions that will handle routing to the\n * right micro-frontends for the provided configuration.\n *\n * @param config - The micro-frontends configuration object.\n * @param flagValues - An object that maps flag names to functions that return the flag value.\n */\nexport function getMicrofrontendsMiddleware({\n request,\n flagValues,\n}: {\n request: NextRequest;\n flagValues?: Record<string, () => Promise<boolean>>;\n}): MicrofrontendsMiddleware[] {\n const microfrontends = MicrofrontendConfigIsomorphic.fromEnv({\n cookies: request.cookies.getAll(),\n });\n const middlewares: MicrofrontendsMiddleware[] = [];\n\n if (!process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION) {\n throw new Error(\n 'The NEXT_PUBLIC_MFE_CURRENT_APPLICATION environment variable is not set. Did you run `withMicrofrontends` in your Next.js config?',\n );\n }\n\n const currentApplication = microfrontends.getApplication(\n process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION,\n );\n\n if (!currentApplication.isDefault()) {\n return middlewares;\n }\n\n const localProxyPort = microfrontends.getLocalProxyPort();\n\n for (const application of microfrontends.getChildApplications()) {\n for (const pathGroup of application.routing) {\n const flagName = pathGroup.flag;\n if (flagName) {\n const flagFn = flagValues?.[flagName];\n if (!flagFn) {\n throw new Error(\n `Flag \"${flagName}\" was specified to control routing for path group \"${pathGroup.group}\" in application ${application.name} but not found in provided flag values. See https://vercel.com/docs/microfrontends/path-routing#add-microfrontends-middleware for more information.`,\n );\n }\n for (const path of pathGroup.paths) {\n const pattern = pathToRegexp(path);\n middlewares.push({\n src: pattern,\n fn: getFlagHandler({\n application,\n flagFn,\n flagName,\n pattern,\n localProxyPort,\n }),\n });\n }\n }\n }\n }\n\n return middlewares;\n}\n\n/**\n * Executes the middlewares returned by `getMicrofrontendsMiddleware` and\n * returns a `Response` if any of the micro-frontends middlewares match or\n * `undefined` if none match. If a `Response` object is returned, the calling\n * code should return that Response from the Next.js middleware in order to\n * stop execution of the middleware and perform the rewrite.\n */\nexport async function runMicrofrontendsMiddleware({\n request,\n flagValues,\n}: {\n request: NextRequest;\n flagValues?: Record<string, () => Promise<boolean>>;\n}): Promise<Response | undefined> {\n const pathname = request.nextUrl.pathname;\n const middlewares = getMicrofrontendsMiddleware({\n request,\n flagValues,\n });\n\n for (const mware of middlewares) {\n if (\n typeof mware.src === 'string'\n ? pathname === mware.src\n : mware.src.test(pathname)\n ) {\n // eslint-disable-next-line no-await-in-loop\n const response = await mware.fn(request);\n if (response) {\n return response;\n }\n }\n }\n}\n","export function routeToLocalProxy(): boolean {\n const isDevEnv = (process.env.VERCEL_ENV ?? 'development') === 'development';\n\n return isDevEnv && Boolean(process.env.TURBO_TASK_HAS_MFE_PROXY);\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 type { ClientConfig } from '../client/types';\nimport { MicrofrontendError } from '../../errors';\nimport { MicrofrontendConfigClient } from '../client';\nimport { type OverridesConfig, parseOverrides } from '../../overrides';\nimport { DefaultApplication, ChildApplication } from './application';\nimport { DEFAULT_LOCAL_PROXY_PORT } from './constants';\nimport {\n validateConfigDefaultApplication,\n validateConfigPaths,\n validateDeprecatedFields,\n} from './validation';\n\ninterface ValidationOptions {\n skipValidation?: 'deprecatedFields'[];\n}\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 opts,\n }: {\n config: Config;\n overrides?: OverridesConfig;\n opts?: ValidationOptions;\n }) {\n // run validation on init\n MicrofrontendConfigIsomorphic.validate(config, opts);\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, opts?: ValidationOptions): Config {\n const skipValidation: ValidationOptions['skipValidation'] =\n opts?.skipValidation ?? [];\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 if (!skipValidation.includes('deprecatedFields')) {\n validateDeprecatedFields(c);\n }\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}\"`,\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 getApplicationByProjectId(\n projectId: string,\n ): DefaultApplication | ChildApplication | undefined {\n // check the default\n if (this.defaultApplication.projectId === projectId) {\n return this.defaultApplication;\n }\n\n return Object.values(this.childApplications).find(\n (app) => app.projectId === projectId,\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 /**\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 toClientConfig(): MicrofrontendConfigClient {\n const applications: ClientConfig['applications'] = Object.fromEntries(\n Object.entries(this.childApplications).map(([name, application]) => [\n name,\n {\n default: false,\n routing: application.routing,\n },\n ]),\n );\n\n // add the default application\n applications[this.defaultApplication.name] = {\n default: true,\n };\n\n return new MicrofrontendConfigClient({\n applications,\n });\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","import { pathToRegexp } from 'path-to-regexp';\nimport type { ClientConfig } from './types';\n\ninterface MicrofrontendConfigClientOptions {\n removeFlaggedPaths?: boolean;\n}\n\nexport class MicrofrontendConfigClient {\n applications: ClientConfig['applications'];\n pathCache: Record<string, string> = {};\n private readonly serialized: ClientConfig;\n\n constructor(config: ClientConfig, opts?: MicrofrontendConfigClientOptions) {\n this.serialized = config;\n if (opts?.removeFlaggedPaths) {\n for (const app of Object.values(config.applications)) {\n if (app.routing) {\n app.routing = app.routing.filter((match) => !match.flag);\n }\n }\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(\n config: string | undefined,\n opts?: MicrofrontendConfigClientOptions,\n ): 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(\n JSON.parse(config) as ClientConfig,\n opts,\n );\n }\n\n isEqual(other: MicrofrontendConfigClient): boolean {\n return (\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 = pathToRegexp(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","// 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, parse as parsePathRegexp } from 'path-to-regexp';\nimport type {\n ApplicationId,\n PathGroup,\n ApplicationRouting,\n ChildApplication as ChildApplicationConfig,\n Config,\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\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};\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\n// TODO: Remove this after 4 May 2025 when the new schema has been fully in use for 30 days and thus we can delete the deprecated fields.\nexport const validateDeprecatedFields = (config: Config): void => {\n const errors = [];\n\n for (const [applicationId, application] of Object.entries(\n config.applications,\n )) {\n if (application.development?.localPort) {\n errors.push(\n `Application '${applicationId}' cannot contain deprecated field 'development.localPort'. Use 'developement.local' instead.`,\n );\n }\n if (application.projectId) {\n // This will be an error in the next release\n }\n }\n\n if (errors.length) {\n throw new MicrofrontendError(\n `Microfrontends configuration file errors:\\n- ${errors.join('\\n- ')}`,\n {\n type: 'config',\n subtype: 'depcrecated_field',\n },\n );\n }\n};\n","const 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}-${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 localPort,\n local,\n }: {\n appName: string;\n localPort?: number;\n local?: string | number | LocalHostConfigSchema;\n }) {\n if (localPort && local) {\n throw new Error(\n `Microfrontends configuration error: '${appName}' has both the 'development.local' and 'development.localPort' fields set. Please remove the 'development.localPort' field and ensure the 'development.local' field has the correct port.`,\n );\n }\n let protocol: RemoteHostConfigSchema['protocol'];\n let host: string | undefined;\n let port: number | undefined;\n if (localPort) {\n port = localPort;\n } else 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 projectId?: string;\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 localPort: app.development?.localPort,\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.projectId = app.projectId;\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 return generateAssetPrefixFromName({ name: this.name });\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":["import_path_to_regexp","import_path_to_regexp","parsePathRegexp"]}
|
package/dist/next/middleware.js
CHANGED
|
@@ -141,7 +141,9 @@ var MicrofrontendConfigClient = class {
|
|
|
141
141
|
*/
|
|
142
142
|
static fromEnv(config, opts) {
|
|
143
143
|
if (!config) {
|
|
144
|
-
throw new Error(
|
|
144
|
+
throw new Error(
|
|
145
|
+
"Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
|
|
146
|
+
);
|
|
145
147
|
}
|
|
146
148
|
return new MicrofrontendConfigClient(
|
|
147
149
|
JSON.parse(config),
|
|
@@ -855,7 +857,9 @@ function getMicrofrontendsMiddleware({
|
|
|
855
857
|
});
|
|
856
858
|
const middlewares = [];
|
|
857
859
|
if (!process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION) {
|
|
858
|
-
throw new Error(
|
|
860
|
+
throw new Error(
|
|
861
|
+
"The NEXT_PUBLIC_MFE_CURRENT_APPLICATION environment variable is not set. Did you run `withMicrofrontends` in your Next.js config?"
|
|
862
|
+
);
|
|
859
863
|
}
|
|
860
864
|
const currentApplication = microfrontends.getApplication(
|
|
861
865
|
process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION
|
|
@@ -871,7 +875,7 @@ function getMicrofrontendsMiddleware({
|
|
|
871
875
|
const flagFn = flagValues?.[flagName];
|
|
872
876
|
if (!flagFn) {
|
|
873
877
|
throw new Error(
|
|
874
|
-
`Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${application.name} but not found in provided flag values.`
|
|
878
|
+
`Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${application.name} but not found in provided flag values. See https://vercel.com/docs/microfrontends/path-routing#add-microfrontends-middleware for more information.`
|
|
875
879
|
);
|
|
876
880
|
}
|
|
877
881
|
for (const path of pathGroup.paths) {
|