UNPKG

@vercel/microfrontends

Version:

Defines configuration and utilities for microfrontends development

125 lines (122 loc) 3.71 kB
// src/next/endpoints/index.ts import { NextResponse } from "next/server"; // src/config/microfrontends-config/client/index.ts import { pathToRegexp } from "path-to-regexp"; var MicrofrontendConfigClient = class { constructor(config, opts) { this.pathCache = {}; this.serialized = config; if (opts?.removeFlaggedPaths) { for (const app of Object.values(config.applications)) { if (app.routing) { app.routing = app.routing.filter((match) => !match.flag); } } } this.applications = config.applications; } /** * Create a new `MicrofrontendConfigClient` from a JSON string. * Config must be passed in to remain framework agnostic */ static fromEnv(config, opts) { if (!config) { throw new Error("No microfrontends configuration found"); } return new MicrofrontendConfigClient( JSON.parse(config), opts ); } isEqual(other) { return JSON.stringify(this.applications) === JSON.stringify(other.applications); } getApplicationNameForPath(path) { if (!path.startsWith("/")) { throw new Error(`Path must start with a /`); } if (this.pathCache[path]) { return this.pathCache[path]; } const pathname = new URL(path, "https://example.com").pathname; for (const [name, application] of Object.entries(this.applications)) { if (application.routing) { for (const group of application.routing) { for (const childPath of group.paths) { const regexp = pathToRegexp(childPath); if (regexp.test(pathname)) { this.pathCache[path] = name; return name; } } } } } const defaultApplication = Object.entries(this.applications).find( ([, application]) => application.default ); if (!defaultApplication) { return null; } this.pathCache[path] = defaultApplication[0]; return defaultApplication[0]; } serialize() { return this.serialized; } }; // src/config/well-known/endpoints.ts async function getWellKnownClientData(clientConfig, flagValues = {}) { const config = MicrofrontendConfigClient.fromEnv(clientConfig); for (const [applicationName, application] of Object.entries( config.applications )) { if (!application.routing) { continue; } const newRoutingMatches = []; for (const pathGroup of application.routing) { if (pathGroup.flag) { const flagName = pathGroup.flag; const flagFn = flagValues[flagName]; if (!flagFn) { throw new Error( `Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${applicationName} but not found in provided flag values.` ); } const flagEnabled = await flagFn(); if (flagEnabled) { newRoutingMatches.push(pathGroup); } } else { newRoutingMatches.push(pathGroup); } } application.routing = newRoutingMatches; } return { config: config.serialize() }; } // src/next/endpoints/index.ts async function wellKnownNextjsClientConfigAppRoute(flagValues) { return NextResponse.json( await getWellKnownClientData( process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG, flagValues ) ); } async function handleClientConfigForPagesRouter(res, flagValues) { const clientData = await getWellKnownClientData( process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG, flagValues ); res.status(200).json(clientData); } export { getWellKnownClientData, handleClientConfigForPagesRouter, wellKnownNextjsClientConfigAppRoute }; //# sourceMappingURL=endpoints.js.map