@vercel/microfrontends
Version:
Defines configuration and utilities for microfrontends development
152 lines (148 loc) • 4.96 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/next/endpoints/index.ts
var endpoints_exports = {};
__export(endpoints_exports, {
getWellKnownClientData: () => getWellKnownClientData,
handleClientConfigForPagesRouter: () => handleClientConfigForPagesRouter,
wellKnownNextjsClientConfigAppRoute: () => wellKnownNextjsClientConfigAppRoute
});
module.exports = __toCommonJS(endpoints_exports);
var import_server = require("next/server");
// src/config/microfrontends-config/client/index.ts
var import_path_to_regexp = require("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 = (0, import_path_to_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 import_server.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);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
getWellKnownClientData,
handleClientConfigForPagesRouter,
wellKnownNextjsClientConfigAppRoute
});
//# sourceMappingURL=endpoints.cjs.map