@vercel/microfrontends
Version:
Defines configuration and utilities for microfrontends development
235 lines (228 loc) • 7.99 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/config/microfrontends/utils/index.ts
var utils_exports = {};
__export(utils_exports, {
findConfig: () => findConfig,
inferMicrofrontendsLocation: () => inferMicrofrontendsLocation
});
module.exports = __toCommonJS(utils_exports);
// src/config/microfrontends/utils/find-config.ts
var import_node_fs = __toESM(require("fs"), 1);
var import_node_path = require("path");
// src/config/constants.ts
var CONFIGURATION_FILENAMES = [
"microfrontends.jsonc",
"microfrontends.json"
];
// src/config/microfrontends/utils/find-config.ts
function findConfig({ dir }) {
for (const filename of CONFIGURATION_FILENAMES) {
const maybeConfig = (0, import_node_path.join)(dir, filename);
if (import_node_fs.default.existsSync(maybeConfig)) {
return maybeConfig;
}
}
return null;
}
// src/config/microfrontends/utils/infer-microfrontends-location.ts
var import_node_path2 = require("path");
var import_node_fs2 = require("fs");
var import_jsonc_parser = require("jsonc-parser");
var import_fast_glob = __toESM(require("fast-glob"), 1);
// src/config/errors.ts
var MicrofrontendError = class extends Error {
constructor(message, opts) {
super(message, { cause: opts?.cause });
this.name = "MicrofrontendsError";
this.source = opts?.source ?? "@vercel/microfrontends";
this.type = opts?.type ?? "unknown";
this.subtype = opts?.subtype;
Error.captureStackTrace(this, MicrofrontendError);
}
isKnown() {
return this.type !== "unknown";
}
isUnknown() {
return !this.isKnown();
}
/**
* Converts an error to a MicrofrontendsError.
* @param original - The original error to convert.
* @returns The converted MicrofrontendsError.
*/
static convert(original, opts) {
if (opts?.fileName) {
const err = MicrofrontendError.convertFSError(original, opts.fileName);
if (err) {
return err;
}
}
if (original.message.includes(
"Code generation from strings disallowed for this context"
)) {
return new MicrofrontendError(original.message, {
type: "config",
subtype: "unsupported_validation_env",
source: "ajv"
});
}
return new MicrofrontendError(original.message);
}
static convertFSError(original, fileName) {
if (original instanceof Error && "code" in original) {
if (original.code === "ENOENT") {
return new MicrofrontendError(`Could not find "${fileName}"`, {
type: "config",
subtype: "unable_to_read_file",
source: "fs"
});
}
if (original.code === "EACCES") {
return new MicrofrontendError(
`Permission denied while accessing "${fileName}"`,
{
type: "config",
subtype: "invalid_permissions",
source: "fs"
}
);
}
}
if (original instanceof SyntaxError) {
return new MicrofrontendError(
`Failed to parse "${fileName}": Invalid JSON format.`,
{
type: "config",
subtype: "invalid_syntax",
source: "fs"
}
);
}
return null;
}
/**
* Handles an unknown error and returns a MicrofrontendsError instance.
* @param err - The error to handle.
* @returns A MicrofrontendsError instance.
*/
static handle(err, opts) {
if (err instanceof MicrofrontendError) {
return err;
}
if (err instanceof Error) {
return MicrofrontendError.convert(err, opts);
}
if (typeof err === "object" && err !== null) {
if ("message" in err && typeof err.message === "string") {
return MicrofrontendError.convert(new Error(err.message), opts);
}
}
return new MicrofrontendError("An unknown error occurred");
}
};
// src/config/microfrontends/utils/infer-microfrontends-location.ts
var configCache = {};
function findPackageWithMicrofrontendsConfig({
repositoryRoot,
applicationName
}) {
try {
const microfrontendsJsonPaths = import_fast_glob.default.globSync(
`**/{${CONFIGURATION_FILENAMES.join(",")}}`,
{
cwd: repositoryRoot,
absolute: true,
onlyFiles: true,
followSymbolicLinks: false,
ignore: ["**/node_modules/**", "**/.git/**"]
}
);
const matchingPaths = [];
for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
try {
const microfrontendsJsonContent = (0, import_node_fs2.readFileSync)(
microfrontendsJsonPath,
"utf-8"
);
const microfrontendsJson = (0, import_jsonc_parser.parse)(microfrontendsJsonContent);
if (microfrontendsJson.applications[applicationName]) {
matchingPaths.push(microfrontendsJsonPath);
} else {
for (const [_, app] of Object.entries(
microfrontendsJson.applications
)) {
if (app.packageName === applicationName) {
matchingPaths.push(microfrontendsJsonPath);
}
}
}
} catch (error) {
}
}
if (matchingPaths.length > 1) {
throw new MicrofrontendError(
`Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
${matchingPaths.join("\n \u2022 ")}`,
{ type: "config", subtype: "inference_failed" }
);
}
if (matchingPaths.length === 0) {
throw new MicrofrontendError(
`Could not find a \`microfrontends.json\` file in the repository that contains "applications.${applicationName}". Microfrontends defined in separate repositories are not supported yet.`,
{ type: "config", subtype: "inference_failed" }
);
}
const [packageJsonPath] = matchingPaths;
return (0, import_node_path2.dirname)(packageJsonPath);
} catch (error) {
return null;
}
}
function inferMicrofrontendsLocation(opts) {
const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;
if (configCache[cacheKey]) {
return configCache[cacheKey];
}
const result = findPackageWithMicrofrontendsConfig(opts);
if (!result) {
throw new MicrofrontendError(
`Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationName}" starting in directory "${opts.repositoryRoot}".`,
{ type: "config", subtype: "inference_failed" }
);
}
configCache[cacheKey] = result;
return result;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
findConfig,
inferMicrofrontendsLocation
});
//# sourceMappingURL=utils.cjs.map