Files
emaui/node_modules/@module-federation/dts-plugin/dist/esm/index.mjs
2026-05-29 15:23:46 +03:00

504 lines
19 KiB
JavaScript

import { a as cloneDeepOptions, c as isTSProject, l as retrieveTypesAssetsInfo, n as RpcGMCallTypes, r as generateTypes, u as validateOptions } from "./expose-rpc-BgxOTFXQ.mjs";
import { s as WEB_CLIENT_OPTIONS_IDENTIFIER } from "./Action-DNNg2YDh.mjs";
import { c as logger$1, o as getIPV4 } from "./Broker-z82OgzMe.mjs";
import { a as createRpcWorker, n as generateTypesInChildProcess, t as consumeTypes } from "./consumeTypes-DCGF9bG3.mjs";
import "./core.mjs";
import fs from "fs";
import * as path$1 from "path";
import path from "path";
import { rm } from "fs/promises";
import { TEMP_DIR, infrastructureLogger, logger, normalizeOptions } from "@module-federation/sdk";
//#region src/dev-worker/DevWorker.ts
var DevWorker = class {
constructor(options) {
this._options = cloneDeepOptions(options);
this.removeUnSerializationOptions();
this._rpcWorker = createRpcWorker(path.resolve(__dirname, "./fork-dev-worker.js"), {}, void 0, false);
this._res = this._rpcWorker.connect(this._options);
}
removeUnSerializationOptions() {
delete this._options.host?.moduleFederationConfig?.manifest;
delete this._options.remote?.moduleFederationConfig?.manifest;
}
get controlledPromise() {
return this._res;
}
update() {
this._rpcWorker.process?.send?.({
type: RpcGMCallTypes.CALL,
id: this._rpcWorker.id,
args: [void 0, "update"]
});
}
exit() {
this._rpcWorker?.terminate();
}
};
//#endregion
//#region src/dev-worker/createDevWorker.ts
async function removeLogFile() {
try {
await rm(path$1.resolve(process.cwd(), ".mf/typesGenerate.log"), {
force: true,
recursive: true
});
} catch (err) {
console.error("removeLogFile error", "forkDevWorker", err);
}
}
function createDevWorker(options) {
removeLogFile();
return new DevWorker({ ...options });
}
//#endregion
//#region src/plugins/utils.ts
function isDev() {
return process.env["NODE_ENV"] === "development";
}
function isPrd() {
return process.env["NODE_ENV"] === "production";
}
function getCompilerOutputDir(compiler) {
try {
return path.relative(compiler.context, compiler.outputPath || compiler.options.output.path);
} catch (err) {
return "";
}
}
//#endregion
//#region src/plugins/DevPlugin.ts
var PROCESS_EXIT_CODE = /* @__PURE__ */ function(PROCESS_EXIT_CODE) {
PROCESS_EXIT_CODE[PROCESS_EXIT_CODE["SUCCESS"] = 0] = "SUCCESS";
PROCESS_EXIT_CODE[PROCESS_EXIT_CODE["FAILURE"] = 1] = "FAILURE";
return PROCESS_EXIT_CODE;
}(PROCESS_EXIT_CODE || {});
function ensureTempDir(filePath) {
try {
const dir = path.dirname(filePath);
fs.mkdirSync(dir, { recursive: true });
} catch (_err) {}
}
var DevPlugin = class DevPlugin {
constructor(options, dtsOptions, generateTypesPromise, fetchRemoteTypeUrlsPromise) {
this.name = "MFDevPlugin";
this._options = options;
this.generateTypesPromise = generateTypesPromise;
this.dtsOptions = dtsOptions;
this.fetchRemoteTypeUrlsPromise = fetchRemoteTypeUrlsPromise;
}
static ensureLiveReloadEntry(options, filePath) {
ensureTempDir(filePath);
const liveReloadEntryWithOptions = fs.readFileSync(path.join(__dirname, "./iife/launch-web-client.iife.js")).toString("utf-8").replace(WEB_CLIENT_OPTIONS_IDENTIFIER, JSON.stringify(options));
fs.writeFileSync(filePath, liveReloadEntryWithOptions);
}
_stopWhenSIGTERMOrSIGINT() {
process.on("SIGTERM", () => {
logger$1.info(`${this._options.name} Process(${process.pid}) SIGTERM, mf server will exit...`);
this._exit(PROCESS_EXIT_CODE.SUCCESS);
});
process.on("SIGINT", () => {
logger$1.info(`${this._options.name} Process(${process.pid}) SIGINT, mf server will exit...`);
this._exit(PROCESS_EXIT_CODE.SUCCESS);
});
}
_handleUnexpectedExit() {
process.on("unhandledRejection", (error) => {
logger$1.error(error);
logger$1.error(`Process(${process.pid}) unhandledRejection, mf server will exit...`);
this._exit(PROCESS_EXIT_CODE.FAILURE);
});
process.on("uncaughtException", (error) => {
logger$1.error(error);
logger$1.error(`Process(${process.pid}) uncaughtException, mf server will exit...`);
this._exit(PROCESS_EXIT_CODE.FAILURE);
});
}
_exit(exitCode = 0) {
this._devWorker?.exit();
process.exit(exitCode);
}
_afterEmit() {
this._devWorker?.update();
}
apply(compiler) {
const { _options: { name, dev, dts } } = this;
const normalizedDev = normalizeOptions(true, {
disableLiveReload: true,
disableHotTypesReload: false,
disableDynamicRemoteTypeHints: false
}, "mfOptions.dev")(dev);
if (!isDev() || normalizedDev === false) return;
new compiler.webpack.DefinePlugin({ FEDERATION_IPV4: JSON.stringify(getIPV4()) }).apply(compiler);
if (normalizedDev.disableHotTypesReload && normalizedDev.disableLiveReload && normalizedDev.disableDynamicRemoteTypeHints) return;
if (!name) throw new Error("name is required if you want to enable dev server!");
if (!normalizedDev.disableDynamicRemoteTypeHints) {
if (!this._options.runtimePlugins) this._options.runtimePlugins = [];
this._options.runtimePlugins.push(path.resolve(__dirname, "dynamic-remote-type-hints-plugin.js"));
}
if (!normalizedDev.disableLiveReload) {
const TEMP_DIR$1 = path.join(`${process.cwd()}/node_modules`, TEMP_DIR);
const filepath = path.join(TEMP_DIR$1, `live-reload.js`);
if (typeof compiler.options.entry === "object") {
DevPlugin.ensureLiveReloadEntry({ name }, filepath);
Object.keys(compiler.options.entry).forEach((entry) => {
const normalizedEntry = compiler.options.entry[entry];
if (typeof normalizedEntry === "object" && Array.isArray(normalizedEntry.import)) normalizedEntry.import.unshift(filepath);
});
}
}
const defaultGenerateTypes = { compileInChildProcess: true };
const defaultConsumeTypes = { consumeAPITypes: true };
const normalizedDtsOptions = normalizeOptions(isTSProject(dts, compiler.context), {
generateTypes: defaultGenerateTypes,
consumeTypes: defaultConsumeTypes,
extraOptions: {},
displayErrorInTerminal: this.dtsOptions?.displayErrorInTerminal
}, "mfOptions.dts")(dts);
const normalizedGenerateTypes = normalizeOptions(Boolean(normalizedDtsOptions), defaultGenerateTypes, "mfOptions.dts.generateTypes")(normalizedDtsOptions === false ? void 0 : normalizedDtsOptions.generateTypes);
const remote = normalizedGenerateTypes === false ? void 0 : {
implementation: normalizedDtsOptions === false ? void 0 : normalizedDtsOptions.implementation,
context: compiler.context,
outputDir: getCompilerOutputDir(compiler),
moduleFederationConfig: { ...this._options },
hostRemoteTypesFolder: normalizedGenerateTypes.typesFolder || "@mf-types",
...normalizedGenerateTypes,
typesFolder: `.dev-server`
};
const normalizedConsumeTypes = normalizeOptions(Boolean(normalizedDtsOptions), defaultConsumeTypes, "mfOptions.dts.consumeTypes")(normalizedDtsOptions === false ? void 0 : normalizedDtsOptions.consumeTypes);
const host = normalizedConsumeTypes === false ? void 0 : {
implementation: normalizedDtsOptions === false ? void 0 : normalizedDtsOptions.implementation,
context: compiler.context,
moduleFederationConfig: this._options,
typesFolder: normalizedConsumeTypes.typesFolder || "@mf-types",
abortOnError: false,
...normalizedConsumeTypes
};
const extraOptions = normalizedDtsOptions ? normalizedDtsOptions.extraOptions || {} : {};
if (!remote && !host && normalizedDev.disableLiveReload) return;
if (remote && !remote?.tsConfigPath && typeof normalizedDtsOptions === "object" && normalizedDtsOptions.tsConfigPath) remote.tsConfigPath = normalizedDtsOptions.tsConfigPath;
Promise.all([this.generateTypesPromise, this.fetchRemoteTypeUrlsPromise]).then(([_, remoteTypeUrls]) => {
this._devWorker = createDevWorker({
name,
remote,
host: {
moduleFederationConfig: {},
...host,
remoteTypeUrls
},
extraOptions,
disableLiveReload: normalizedDev.disableHotTypesReload,
disableHotTypesReload: normalizedDev.disableHotTypesReload
});
});
this._stopWhenSIGTERMOrSIGINT();
this._handleUnexpectedExit();
compiler.hooks.afterEmit.tap(this.name, this._afterEmit.bind(this));
}
};
//#endregion
//#region src/plugins/ConsumeTypesPlugin.ts
const DEFAULT_CONSUME_TYPES = {
abortOnError: false,
consumeAPITypes: true,
typesOnBuild: false
};
const normalizeConsumeTypesOptions = ({ context, dtsOptions, pluginOptions }) => {
const normalizedConsumeTypes = normalizeOptions(true, DEFAULT_CONSUME_TYPES, "mfOptions.dts.consumeTypes")(dtsOptions.consumeTypes);
if (!normalizedConsumeTypes) return;
const dtsManagerOptions = {
host: {
implementation: dtsOptions.implementation,
context,
moduleFederationConfig: pluginOptions,
...normalizedConsumeTypes
},
extraOptions: dtsOptions.extraOptions || {},
displayErrorInTerminal: dtsOptions.displayErrorInTerminal
};
validateOptions(dtsManagerOptions.host);
return dtsManagerOptions;
};
const consumeTypesAPI = async (dtsManagerOptions, cb) => {
return (typeof dtsManagerOptions.host.remoteTypeUrls === "function" ? dtsManagerOptions.host.remoteTypeUrls() : Promise.resolve(dtsManagerOptions.host.remoteTypeUrls)).then((remoteTypeUrls) => {
consumeTypes({
...dtsManagerOptions,
host: {
...dtsManagerOptions.host,
remoteTypeUrls
}
}).then(() => {
typeof cb === "function" && cb(remoteTypeUrls);
}).catch(() => {
typeof cb === "function" && cb(remoteTypeUrls);
});
});
};
var ConsumeTypesPlugin = class {
constructor(pluginOptions, dtsOptions, fetchRemoteTypeUrlsResolve) {
this.pluginOptions = pluginOptions;
this.dtsOptions = dtsOptions;
this.fetchRemoteTypeUrlsResolve = fetchRemoteTypeUrlsResolve;
}
apply(compiler) {
const { dtsOptions, pluginOptions, fetchRemoteTypeUrlsResolve } = this;
const dtsManagerOptions = normalizeConsumeTypesOptions({
context: compiler.context,
dtsOptions,
pluginOptions
});
if (!dtsManagerOptions) {
fetchRemoteTypeUrlsResolve(void 0);
return;
}
if (isPrd() && !dtsManagerOptions.host.typesOnBuild) {
fetchRemoteTypeUrlsResolve(void 0);
return;
}
infrastructureLogger.debug("start fetching remote types...");
const promise = consumeTypesAPI(dtsManagerOptions, fetchRemoteTypeUrlsResolve);
compiler.hooks.thisCompilation.tap("mf:generateTypes", (compilation) => {
compilation.hooks.processAssets.tapPromise({
name: "mf:generateTypes",
stage: compilation.constructor.PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER - 1
}, async () => {
await promise;
infrastructureLogger.debug("fetch remote types success!");
});
});
}
};
//#endregion
//#region src/plugins/GenerateTypesPlugin.ts
const DEFAULT_GENERATE_TYPES = {
generateAPITypes: true,
compileInChildProcess: true,
abortOnError: false,
extractThirdParty: false,
extractRemoteTypes: false
};
const normalizeGenerateTypesOptions = ({ context, outputDir, dtsOptions, pluginOptions }) => {
const normalizedGenerateTypes = normalizeOptions(true, DEFAULT_GENERATE_TYPES, "mfOptions.dts.generateTypes")(dtsOptions.generateTypes);
if (!normalizedGenerateTypes) return;
const normalizedConsumeTypes = normalizeOptions(true, {}, "mfOptions.dts.consumeTypes")(dtsOptions.consumeTypes);
const finalOptions = {
remote: {
implementation: dtsOptions.implementation,
context,
outputDir,
moduleFederationConfig: pluginOptions,
...normalizedGenerateTypes
},
host: normalizedConsumeTypes === false ? void 0 : {
context,
moduleFederationConfig: pluginOptions,
...normalizedConsumeTypes,
remoteTypeUrls: typeof normalizedConsumeTypes?.remoteTypeUrls === "object" ? normalizedConsumeTypes?.remoteTypeUrls : void 0
},
extraOptions: dtsOptions.extraOptions || {},
displayErrorInTerminal: dtsOptions.displayErrorInTerminal
};
if (dtsOptions.tsConfigPath && !finalOptions.remote.tsConfigPath) finalOptions.remote.tsConfigPath = dtsOptions.tsConfigPath;
validateOptions(finalOptions.remote);
return finalOptions;
};
const getGenerateTypesFn = (dtsManagerOptions) => {
let fn = generateTypes;
if (dtsManagerOptions.remote.compileInChildProcess) fn = generateTypesInChildProcess;
return fn;
};
const generateTypesAPI = ({ dtsManagerOptions }) => {
return getGenerateTypesFn(dtsManagerOptions)(dtsManagerOptions).then(async () => {
await callAfterGenerateHook({
dtsManagerOptions,
generatedTypes: retrieveTypesAssetsInfo(dtsManagerOptions.remote)
});
});
};
const callAfterGenerateHook = async ({ dtsManagerOptions, generatedTypes }) => {
const afterGenerate = dtsManagerOptions.remote.afterGenerate;
if (!afterGenerate) return;
try {
await afterGenerate(generatedTypes);
} catch (error) {
if (dtsManagerOptions.remote.abortOnError === false) {
if (dtsManagerOptions.displayErrorInTerminal) logger.error(error);
return;
}
throw error;
}
};
const WINDOWS_ABSOLUTE_PATH_REGEXP = /^[a-zA-Z]:[\\/]/;
const isSafeRelativePath = (relativePath) => {
return Boolean(relativePath) && !relativePath.startsWith("..") && !path.isAbsolute(relativePath) && !WINDOWS_ABSOLUTE_PATH_REGEXP.test(relativePath);
};
const resolveEmitAssetName = ({ compilerOutputPath, assetPath, fallbackName }) => {
if (!assetPath) return fallbackName;
const relativePath = path.relative(compilerOutputPath, assetPath);
return isSafeRelativePath(relativePath) ? relativePath : fallbackName;
};
var GenerateTypesPlugin = class {
constructor(pluginOptions, dtsOptions, fetchRemoteTypeUrlsPromise, callback) {
this.pluginOptions = pluginOptions;
this.dtsOptions = dtsOptions;
this.fetchRemoteTypeUrlsPromise = fetchRemoteTypeUrlsPromise;
this.callback = callback;
}
apply(compiler) {
const { dtsOptions, pluginOptions, fetchRemoteTypeUrlsPromise, callback } = this;
const outputDir = getCompilerOutputDir(compiler);
const context = compiler.context;
const dtsManagerOptions = normalizeGenerateTypesOptions({
context,
outputDir,
dtsOptions,
pluginOptions
});
if (!dtsManagerOptions) {
callback();
return;
}
const isProd = !isDev();
const compilerOutputPath = path.resolve(context, outputDir);
const emitTypesFiles = async (compilation) => {
try {
const { zipTypesPath, apiTypesPath, zipName, apiFileName } = retrieveTypesAssetsInfo(dtsManagerOptions.remote);
const emitZipName = resolveEmitAssetName({
compilerOutputPath,
assetPath: zipTypesPath,
fallbackName: zipName
});
const emitApiFileName = resolveEmitAssetName({
compilerOutputPath,
assetPath: apiTypesPath,
fallbackName: apiFileName
});
if (isProd && emitZipName && compilation.getAsset(emitZipName)) {
callback();
return;
}
logger.debug("start generating types...");
await generateTypesAPI({ dtsManagerOptions });
logger.debug("generate types success!");
if (isProd) {
if (zipTypesPath && !compilation.getAsset(emitZipName) && fs.existsSync(zipTypesPath)) compilation.emitAsset(emitZipName, new compiler.webpack.sources.RawSource(fs.readFileSync(zipTypesPath)));
if (apiTypesPath && !compilation.getAsset(emitApiFileName) && fs.existsSync(apiTypesPath)) compilation.emitAsset(emitApiFileName, new compiler.webpack.sources.RawSource(fs.readFileSync(apiTypesPath)));
callback();
} else {
const isEEXIST = (err) => {
return err.code == "EEXIST";
};
if (zipTypesPath && fs.existsSync(zipTypesPath)) {
const zipContent = fs.readFileSync(zipTypesPath);
const zipOutputPath = path.join(compiler.outputPath, emitZipName);
await new Promise((resolve, reject) => {
compiler.outputFileSystem.mkdir(path.dirname(zipOutputPath), { recursive: true }, (err) => {
if (err && !isEEXIST(err)) reject(err);
else compiler.outputFileSystem.writeFile(zipOutputPath, zipContent, (writeErr) => {
if (writeErr && !isEEXIST(writeErr)) reject(writeErr);
else resolve();
});
});
});
}
if (apiTypesPath && fs.existsSync(apiTypesPath)) {
const apiContent = fs.readFileSync(apiTypesPath);
const apiOutputPath = path.join(compiler.outputPath, emitApiFileName);
await new Promise((resolve, reject) => {
compiler.outputFileSystem.mkdir(path.dirname(apiOutputPath), { recursive: true }, (err) => {
if (err && !isEEXIST(err)) reject(err);
else compiler.outputFileSystem.writeFile(apiOutputPath, apiContent, (writeErr) => {
if (writeErr && !isEEXIST(writeErr)) reject(writeErr);
else resolve();
});
});
});
}
callback();
}
} catch (err) {
callback();
if (dtsManagerOptions.displayErrorInTerminal) console.error(err);
logger.debug("generate types fail!");
}
};
compiler.hooks.thisCompilation.tap("mf:generateTypes", (compilation) => {
compilation.hooks.processAssets.tapPromise({
name: "mf:generateTypes",
stage: compilation.constructor.PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER
}, async () => {
await fetchRemoteTypeUrlsPromise;
const emitTypesFilesPromise = emitTypesFiles(compilation);
if (isProd) await emitTypesFilesPromise;
});
});
}
};
//#endregion
//#region src/plugins/DtsPlugin.ts
const normalizeDtsOptions = (options, context, defaultOptions) => {
return normalizeOptions(isTSProject(options.dts, context), {
generateTypes: defaultOptions?.defaultGenerateOptions || DEFAULT_GENERATE_TYPES,
consumeTypes: defaultOptions?.defaultConsumeOptions || DEFAULT_CONSUME_TYPES,
extraOptions: {},
displayErrorInTerminal: true
}, "mfOptions.dts")(options.dts);
};
const excludeDts = (filepath) => {
if (typeof filepath !== "string") return false;
const [_p, query] = filepath.split("?");
if (query && query.startsWith("exclude-mf-dts")) return true;
return false;
};
var DtsPlugin = class {
constructor(options) {
this.options = options;
this.clonedOptions = { ...options };
}
apply(compiler) {
const { options, clonedOptions } = this;
if (options.exposes && typeof options.exposes === "object") {
const cleanedExposes = {};
Object.entries(options.exposes).forEach(([key, value]) => {
if (typeof value === "string") {
const [filepath, _query] = value.split("?");
if (excludeDts(value)) return;
cleanedExposes[key] = filepath;
} else {
if (typeof value === "object" && Array.isArray(value.import) && value.import.some((v) => excludeDts(v))) return;
cleanedExposes[key] = value;
}
});
clonedOptions.exposes = cleanedExposes;
}
const normalizedDtsOptions = normalizeDtsOptions(clonedOptions, compiler.context);
if (typeof normalizedDtsOptions !== "object") return;
let fetchRemoteTypeUrlsResolve;
const fetchRemoteTypeUrlsPromise = new Promise((resolve) => {
fetchRemoteTypeUrlsResolve = resolve;
});
let generateTypesPromiseResolve;
new DevPlugin(clonedOptions, normalizedDtsOptions, new Promise((resolve) => {
generateTypesPromiseResolve = resolve;
}), fetchRemoteTypeUrlsPromise).apply(compiler);
new GenerateTypesPlugin(clonedOptions, normalizedDtsOptions, fetchRemoteTypeUrlsPromise, generateTypesPromiseResolve).apply(compiler);
new ConsumeTypesPlugin(clonedOptions, normalizedDtsOptions, fetchRemoteTypeUrlsResolve).apply(compiler);
}
addRuntimePlugins() {
const { options, clonedOptions } = this;
if (!clonedOptions.runtimePlugins) return;
if (!options.runtimePlugins) options.runtimePlugins = [];
clonedOptions.runtimePlugins.forEach((plugin) => {
options.runtimePlugins.includes(plugin) || options.runtimePlugins.push(plugin);
});
}
};
//#endregion
export { DtsPlugin, consumeTypesAPI, generateTypesAPI, isTSProject, normalizeConsumeTypesOptions, normalizeDtsOptions, normalizeGenerateTypesOptions };