Project Init

This commit is contained in:
Muluhabt
2026-05-29 15:23:46 +03:00
commit 2fbc557aac
67387 changed files with 6063341 additions and 0 deletions

View File

@@ -0,0 +1,153 @@
//#region \0rolldown/runtime.js
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 __exportAll = (all, no_symbols) => {
let target = {};
for (var name in all) {
__defProp(target, name, {
get: all[name],
enumerable: true
});
}
if (!no_symbols) {
__defProp(target, Symbol.toStringTag, { value: "Module" });
}
return target;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) {
__defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
}
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
//#region src/server/message/Message.ts
var Message = class {
constructor(type, kind) {
this.type = type;
this.kind = kind;
this.time = Date.now();
}
};
//#endregion
//#region src/server/constant.ts
const DEFAULT_WEB_SOCKET_PORT = 16322;
const WEB_SOCKET_CONNECT_MAGIC_ID = "1hpzW-zo2z-o8io-gfmV1-2cb1d82";
const MF_SERVER_IDENTIFIER = "Module Federation DTS";
const WEB_CLIENT_OPTIONS_IDENTIFIER = "__WEB_CLIENT_OPTIONS__";
const DEFAULT_TAR_NAME = "@mf-types.zip";
let UpdateMode = /* @__PURE__ */ function(UpdateMode) {
UpdateMode["POSITIVE"] = "POSITIVE";
UpdateMode["PASSIVE"] = "PASSIVE";
return UpdateMode;
}({});
//#endregion
//#region src/server/message/Action/Action.ts
let ActionKind = /* @__PURE__ */ function(ActionKind) {
ActionKind["ADD_SUBSCRIBER"] = "ADD_SUBSCRIBER";
ActionKind["EXIT_SUBSCRIBER"] = "EXIT_SUBSCRIBER";
ActionKind["ADD_PUBLISHER"] = "ADD_PUBLISHER";
ActionKind["UPDATE_PUBLISHER"] = "UPDATE_PUBLISHER";
ActionKind["NOTIFY_SUBSCRIBER"] = "NOTIFY_SUBSCRIBER";
ActionKind["EXIT_PUBLISHER"] = "EXIT_PUBLISHER";
ActionKind["ADD_WEB_CLIENT"] = "ADD_WEB_CLIENT";
ActionKind["NOTIFY_WEB_CLIENT"] = "NOTIFY_WEB_CLIENT";
ActionKind["FETCH_TYPES"] = "FETCH_TYPES";
ActionKind["ADD_DYNAMIC_REMOTE"] = "ADD_DYNAMIC_REMOTE";
return ActionKind;
}({});
var Action = class extends Message {
constructor(content, kind) {
super("Action", kind);
const { payload } = content;
this.payload = payload;
}
};
//#endregion
Object.defineProperty(exports, 'Action', {
enumerable: true,
get: function () {
return Action;
}
});
Object.defineProperty(exports, 'ActionKind', {
enumerable: true,
get: function () {
return ActionKind;
}
});
Object.defineProperty(exports, 'DEFAULT_TAR_NAME', {
enumerable: true,
get: function () {
return DEFAULT_TAR_NAME;
}
});
Object.defineProperty(exports, 'DEFAULT_WEB_SOCKET_PORT', {
enumerable: true,
get: function () {
return DEFAULT_WEB_SOCKET_PORT;
}
});
Object.defineProperty(exports, 'MF_SERVER_IDENTIFIER', {
enumerable: true,
get: function () {
return MF_SERVER_IDENTIFIER;
}
});
Object.defineProperty(exports, 'Message', {
enumerable: true,
get: function () {
return Message;
}
});
Object.defineProperty(exports, 'UpdateMode', {
enumerable: true,
get: function () {
return UpdateMode;
}
});
Object.defineProperty(exports, 'WEB_CLIENT_OPTIONS_IDENTIFIER', {
enumerable: true,
get: function () {
return WEB_CLIENT_OPTIONS_IDENTIFIER;
}
});
Object.defineProperty(exports, 'WEB_SOCKET_CONNECT_MAGIC_ID', {
enumerable: true,
get: function () {
return WEB_SOCKET_CONNECT_MAGIC_ID;
}
});
Object.defineProperty(exports, '__exportAll', {
enumerable: true,
get: function () {
return __exportAll;
}
});
Object.defineProperty(exports, '__toESM', {
enumerable: true,
get: function () {
return __toESM;
}
});

View File

@@ -0,0 +1,783 @@
const require_Action = require('./Action-CzhPMw2i.js');
let fs = require("fs");
fs = require_Action.__toESM(fs);
let path = require("path");
path = require_Action.__toESM(path);
let _module_federation_sdk = require("@module-federation/sdk");
let net = require("net");
net = require_Action.__toESM(net);
let os = require("os");
os = require_Action.__toESM(os);
let isomorphic_ws = require("isomorphic-ws");
isomorphic_ws = require_Action.__toESM(isomorphic_ws);
let http = require("http");
let node_schedule = require("node-schedule");
node_schedule = require_Action.__toESM(node_schedule);
let url = require("url");
//#region src/server/message/API/API.ts
let APIKind = /* @__PURE__ */ function(APIKind) {
APIKind["UPDATE_SUBSCRIBER"] = "UPDATE_SUBSCRIBER";
APIKind["RELOAD_WEB_CLIENT"] = "RELOAD_WEB_CLIENT";
APIKind["FETCH_TYPES"] = "FETCH_TYPES";
return APIKind;
}({});
var API = class extends require_Action.Message {
constructor(content, kind) {
super("API", kind);
const { code, payload } = content;
this.code = code;
this.payload = payload;
}
};
//#endregion
//#region src/server/message/API/UpdateSubscriber.ts
var UpdateSubscriberAPI = class extends API {
constructor(payload) {
super({
code: 0,
payload
}, APIKind.UPDATE_SUBSCRIBER);
}
};
//#endregion
//#region src/server/message/API/ReloadWebClient.ts
var ReloadWebClientAPI = class extends API {
constructor(payload) {
super({
code: 0,
payload
}, APIKind.RELOAD_WEB_CLIENT);
}
};
//#endregion
//#region src/server/message/API/FetchTypes.ts
var FetchTypesAPI = class extends API {
constructor(payload) {
super({
code: 0,
payload
}, APIKind.FETCH_TYPES);
}
};
//#endregion
//#region src/server/message/Log/Log.ts
let LogLevel = /* @__PURE__ */ function(LogLevel) {
LogLevel["LOG"] = "LOG";
LogLevel["WARN"] = "WARN";
LogLevel["ERROR"] = "ERROR";
return LogLevel;
}({});
let LogKind = /* @__PURE__ */ function(LogKind) {
LogKind["BrokerExitLog"] = "BrokerExitLog";
LogKind["PublisherRegisteredLog"] = "PublisherRegisteredLog";
return LogKind;
}({});
var Log = class extends require_Action.Message {
constructor(level, kind, ignoreVerbose = false) {
super("Log", kind);
this.ignoreVerbose = false;
this.level = level;
this.ignoreVerbose = ignoreVerbose;
}
};
//#endregion
//#region src/server/message/Log/BrokerExitLog.ts
var BrokerExitLog = class extends Log {
constructor() {
super(LogLevel.LOG, LogKind.BrokerExitLog);
}
};
//#endregion
//#region src/server/utils/log.ts
const logger = (0, _module_federation_sdk.createLogger)(`[ ${require_Action.MF_SERVER_IDENTIFIER} ]`);
function fileLog(msg, module, level) {
if (!process?.env?.["FEDERATION_DEBUG"]) return;
try {
const logDir = ".mf";
const logFile = path.join(logDir, "typesGenerate.log");
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
if (!fs.existsSync(logDir)) fs.mkdirSync(logDir, { recursive: true });
fs.appendFileSync(logFile, `[${timestamp}] [${level.toUpperCase()}] ${module} - ${msg}\n`);
} catch {}
}
function error(error, action, from) {
const err = error instanceof Error ? error : /* @__PURE__ */ new Error(`${action} error`);
fileLog(`[${action}] error: ${err}`, from, "fatal");
return err.toString();
}
//#endregion
//#region src/server/utils/getIPV4.ts
const localIpv4 = "127.0.0.1";
const getIpv4Interfaces = () => {
try {
const interfaces = os.default.networkInterfaces();
const ipv4Interfaces = [];
Object.values(interfaces).forEach((detail) => {
detail?.forEach((detail) => {
const familyV4Value = typeof detail.family === "string" ? "IPv4" : 4;
if (detail.family === familyV4Value && detail.address !== localIpv4) ipv4Interfaces.push(detail);
});
});
return ipv4Interfaces;
} catch (_err) {
return [];
}
};
const getIPV4 = () => {
return (getIpv4Interfaces()[0] || { address: localIpv4 }).address;
};
//#endregion
//#region src/server/utils/index.ts
function getIdentifier(options) {
const { ip, name } = options;
return `mf ${_module_federation_sdk.SEPARATOR}${name}${ip ? `${_module_federation_sdk.SEPARATOR}${ip}` : ""}`;
}
function fib(n) {
let i = 2;
const res = [
0,
1,
1
];
while (i <= n) {
res[i] = res[i - 1] + res[i - 2];
i++;
}
return res[n];
}
function getFreePort() {
return new Promise((resolve, reject) => {
const server = net.default.createServer();
server.unref();
server.on("error", reject);
server.listen(0, () => {
const { port } = server.address();
server.close(() => {
resolve(port);
});
});
});
}
//#endregion
//#region src/server/Publisher.ts
var Publisher = class {
constructor(ctx) {
this._name = ctx.name;
this._ip = ctx.ip;
this._remoteTypeTarPath = ctx.remoteTypeTarPath;
this._subscribers = /* @__PURE__ */ new Map();
this._ws = ctx.ws;
this.dynamicRemoteMap = /* @__PURE__ */ new Map();
}
get identifier() {
return getIdentifier({
name: this._name,
ip: this._ip
});
}
get name() {
return this._name;
}
get ip() {
return this._ip;
}
get remoteTypeTarPath() {
return this._remoteTypeTarPath;
}
get hasSubscribes() {
return Boolean(this._subscribers.size);
}
get subscribers() {
return this._subscribers;
}
addSubscriber(identifier, subscriber) {
fileLog(`${this.name} set subscriber: ${identifier}`, "Publisher", "info");
this._subscribers.set(identifier, subscriber);
}
removeSubscriber(identifier) {
if (this._subscribers.has(identifier)) {
fileLog(`${this.name} removeSubscriber: ${identifier}`, "Publisher", "warn");
this._subscribers.delete(identifier);
}
}
notifySubscriber(subscriberIdentifier, options) {
const subscriber = this._subscribers.get(subscriberIdentifier);
if (!subscriber) {
fileLog(`[notifySubscriber] ${this.name} notifySubscriber: ${subscriberIdentifier}, does not exits`, "Publisher", "error");
return;
}
const api = new UpdateSubscriberAPI(options);
subscriber.send(JSON.stringify(api));
fileLog(`[notifySubscriber] ${this.name} notifySubscriber: ${JSON.stringify(subscriberIdentifier)}, message: ${JSON.stringify(api)}`, "Publisher", "info");
}
fetchRemoteTypes(options) {
fileLog(`[fetchRemoteTypes] ${this.name} fetchRemoteTypes, options: ${JSON.stringify(options)}, ws: ${Boolean(this._ws)}`, "Publisher", "info");
if (!this._ws) return;
const api = new FetchTypesAPI(options);
this._ws.send(JSON.stringify(api));
}
notifySubscribers(options) {
const api = new UpdateSubscriberAPI(options);
this.broadcast(api);
}
broadcast(message) {
if (this.hasSubscribes) this._subscribers.forEach((subscriber, key) => {
fileLog(`[BroadCast] ${this.name} notifySubscriber: ${key}, PID: ${process.pid}, message: ${JSON.stringify(message)}`, "Publisher", "info");
subscriber.send(JSON.stringify(message));
});
else fileLog(`[BroadCast] ${this.name}'s subscribe is empty`, "Publisher", "warn");
}
close() {
this._ws = void 0;
this._subscribers.forEach((_subscriber, identifier) => {
fileLog(`[BroadCast] close ${this.name} remove: ${identifier}`, "Publisher", "warn");
this.removeSubscriber(identifier);
});
}
};
//#endregion
//#region src/server/message/Action/Update.ts
let UpdateKind = /* @__PURE__ */ function(UpdateKind) {
UpdateKind["UPDATE_TYPE"] = "UPDATE_TYPE";
UpdateKind["RELOAD_PAGE"] = "RELOAD_PAGE";
return UpdateKind;
}({});
//#endregion
//#region src/server/broker/Broker.ts
var Broker = class Broker {
static {
this.WEB_SOCKET_CONNECT_MAGIC_ID = require_Action.WEB_SOCKET_CONNECT_MAGIC_ID;
}
static {
this.DEFAULT_WEB_SOCKET_PORT = require_Action.DEFAULT_WEB_SOCKET_PORT;
}
static {
this.DEFAULT_SECURE_WEB_SOCKET_PORT = 16324;
}
static {
this.DEFAULT_WAITING_TIME = 1.5 * 60 * 60 * 1e3;
}
constructor() {
this._publisherMap = /* @__PURE__ */ new Map();
this._webClientMap = /* @__PURE__ */ new Map();
this._tmpSubscriberShelter = /* @__PURE__ */ new Map();
this._scheduleJob = null;
this._setSchedule();
this._startWsServer();
this._stopWhenSIGTERMOrSIGINT();
this._handleUnexpectedExit();
}
get hasPublishers() {
return Boolean(this._publisherMap.size);
}
async _startWsServer() {
const wsHandler = (ws, req) => {
const { url: reqUrl = "" } = req;
const { query } = (0, url.parse)(reqUrl, true);
const { WEB_SOCKET_CONNECT_MAGIC_ID } = query;
if (WEB_SOCKET_CONNECT_MAGIC_ID === Broker.WEB_SOCKET_CONNECT_MAGIC_ID) {
ws.on("message", (message) => {
try {
const text = message.toString();
const action = JSON.parse(text);
fileLog(`${action?.kind} action received `, "Broker", "info");
this._takeAction(action, ws);
} catch (error) {
fileLog(`parse action message error: ${error}`, "Broker", "error");
}
});
ws.on("error", (e) => {
fileLog(`parse action message error: ${e}`, "Broker", "error");
});
} else {
ws.send("Invalid CONNECT ID.");
fileLog("Invalid CONNECT ID.", "Broker", "warn");
ws.close();
}
};
const server = (0, http.createServer)();
this._webSocketServer = new isomorphic_ws.default.Server({ noServer: true });
this._webSocketServer.on("error", (err) => {
fileLog(`ws error: \n${err.message}\n ${err.stack}`, "Broker", "error");
});
this._webSocketServer.on("listening", () => {
fileLog(`WebSocket server is listening on port ${Broker.DEFAULT_WEB_SOCKET_PORT}`, "Broker", "info");
});
this._webSocketServer.on("connection", wsHandler);
this._webSocketServer.on("close", (code) => {
fileLog(`WebSocket Server Close with Code ${code}`, "Broker", "warn");
this._webSocketServer && this._webSocketServer.close();
this._webSocketServer = void 0;
});
server.on("upgrade", (req, socket, head) => {
if (req.url) {
const { pathname } = (0, url.parse)(req.url);
if (pathname === "/") this._webSocketServer?.handleUpgrade(req, socket, head, (ws) => {
this._webSocketServer?.emit("connection", ws, req);
});
}
});
server.listen(Broker.DEFAULT_WEB_SOCKET_PORT);
}
async _takeAction(action, client) {
const { kind, payload } = action;
if (kind === require_Action.ActionKind.ADD_PUBLISHER) await this._addPublisher(payload, client);
if (kind === require_Action.ActionKind.UPDATE_PUBLISHER) await this._updatePublisher(payload, client);
if (kind === require_Action.ActionKind.ADD_SUBSCRIBER) await this._addSubscriber(payload, client);
if (kind === require_Action.ActionKind.EXIT_SUBSCRIBER) await this._removeSubscriber(payload, client);
if (kind === require_Action.ActionKind.EXIT_PUBLISHER) await this._removePublisher(payload, client);
if (kind === require_Action.ActionKind.ADD_WEB_CLIENT) await this._addWebClient(payload, client);
if (kind === require_Action.ActionKind.NOTIFY_WEB_CLIENT) await this._notifyWebClient(payload, client);
if (kind === require_Action.ActionKind.FETCH_TYPES) await this._fetchTypes(payload, client);
if (kind === require_Action.ActionKind.ADD_DYNAMIC_REMOTE) this._addDynamicRemote(payload);
}
async _addPublisher(context, client) {
const { name, ip, remoteTypeTarPath } = context ?? {};
const identifier = getIdentifier({
name,
ip
});
if (this._publisherMap.has(identifier)) {
fileLog(`[${require_Action.ActionKind.ADD_PUBLISHER}] ${identifier} has been added, this action will be ignored`, "Broker", "warn");
return;
}
try {
const publisher = new Publisher({
name,
ip,
remoteTypeTarPath,
ws: client
});
this._publisherMap.set(identifier, publisher);
fileLog(`[${require_Action.ActionKind.ADD_PUBLISHER}] ${identifier} Adding Publisher Succeed`, "Broker", "info");
const tmpSubScribers = this._getTmpSubScribers(identifier);
if (tmpSubScribers) {
fileLog(`[${require_Action.ActionKind.ADD_PUBLISHER}] consumeTmpSubscriber set ${publisher.name}s subscribers `, "Broker", "info");
this._consumeTmpSubScribers(publisher, tmpSubScribers);
this._clearTmpSubScriberRelation(identifier);
}
} catch (err) {
const msg = error(err, require_Action.ActionKind.ADD_PUBLISHER, "Broker");
client.send(msg);
client.close();
}
}
async _updatePublisher(context, client) {
const { name, updateMode, updateKind, updateSourcePaths, remoteTypeTarPath, ip } = context ?? {};
const identifier = getIdentifier({
name,
ip
});
if (!this._publisherMap.has(identifier)) {
fileLog(`[${require_Action.ActionKind.UPDATE_PUBLISHER}] ${identifier} has not been started, this action will be ignored
this._publisherMap: ${JSON.stringify(this._publisherMap.entries())}
`, "Broker", "warn");
return;
}
try {
const publisher = this._publisherMap.get(identifier);
fileLog(`[${require_Action.ActionKind.UPDATE_PUBLISHER}] ${identifier} update, and notify subscribers to update`, "Broker", "info");
if (publisher) {
publisher.notifySubscribers({
remoteTypeTarPath,
name,
updateMode,
updateKind,
updateSourcePaths: updateSourcePaths || []
});
this._publisherMap.forEach((p) => {
if (p.name === publisher.name) return;
const dynamicRemoteInfo = p.dynamicRemoteMap.get(identifier);
if (dynamicRemoteInfo) {
fileLog(`dynamicRemoteInfo: ${JSON.stringify(dynamicRemoteInfo)}, identifier:${identifier} publish: ${p.name}`, "Broker", "info");
p.fetchRemoteTypes({
remoteInfo: dynamicRemoteInfo,
once: false
});
}
});
}
} catch (err) {
const msg = error(err, require_Action.ActionKind.UPDATE_PUBLISHER, "Broker");
client.send(msg);
client.close();
}
}
async _fetchTypes(context, _client) {
const { name, ip, remoteInfo } = context ?? {};
const identifier = getIdentifier({
name,
ip
});
try {
const publisher = this._publisherMap.get(identifier);
fileLog(`[${require_Action.ActionKind.FETCH_TYPES}] ${identifier} fetch types`, "Broker", "info");
if (publisher) publisher.fetchRemoteTypes({
remoteInfo,
once: true
});
} catch (err) {
fileLog(`[${require_Action.ActionKind.FETCH_TYPES}] ${identifier} fetch types fail , error info: ${err}`, "Broker", "error");
}
}
_addDynamicRemote(context) {
const { name, ip, remoteInfo, remoteIp } = context ?? {};
const identifier = getIdentifier({
name,
ip
});
const publisher = this._publisherMap.get(identifier);
const remoteId = getIdentifier({
name: remoteInfo.name,
ip: remoteIp
});
fileLog(`[${require_Action.ActionKind.ADD_DYNAMIC_REMOTE}] identifier:${identifier},publisher: ${publisher.name}, remoteId:${remoteId}`, "Broker", "error");
if (!publisher || publisher.dynamicRemoteMap.has(remoteId)) return;
publisher.dynamicRemoteMap.set(remoteId, remoteInfo);
}
async _addSubscriber(context, client) {
const { publishers, name: subscriberName } = context ?? {};
publishers.forEach((publisher) => {
const { name, ip } = publisher;
const identifier = getIdentifier({
name,
ip
});
if (!this._publisherMap.has(identifier)) {
fileLog(`[${require_Action.ActionKind.ADD_SUBSCRIBER}]: ${identifier} has not been started, ${subscriberName} will add the relation to tmp shelter`, "Broker", "warn");
this._addTmpSubScriberRelation({
name: getIdentifier({
name: context.name,
ip: context.ip
}),
client
}, publisher);
return;
}
try {
const registeredPublisher = this._publisherMap.get(identifier);
if (registeredPublisher) {
registeredPublisher.addSubscriber(getIdentifier({
name: subscriberName,
ip: context.ip
}), client);
fileLog(`[${require_Action.ActionKind.ADD_SUBSCRIBER}]: ${identifier} has been started, Adding Subscriber ${subscriberName} Succeed, this.__publisherMap are: ${JSON.stringify(Array.from(this._publisherMap.entries()))}`, "Broker", "info");
registeredPublisher.notifySubscriber(getIdentifier({
name: subscriberName,
ip: context.ip
}), {
updateKind: UpdateKind.UPDATE_TYPE,
updateMode: require_Action.UpdateMode.PASSIVE,
updateSourcePaths: [registeredPublisher.name],
remoteTypeTarPath: registeredPublisher.remoteTypeTarPath,
name: registeredPublisher.name
});
fileLog(`[${require_Action.ActionKind.ADD_SUBSCRIBER}]: notifySubscriber Subscriber ${subscriberName}, updateMode: "PASSIVE", updateSourcePaths: ${registeredPublisher.name}`, "Broker", "info");
}
} catch (err) {
const msg = error(err, require_Action.ActionKind.ADD_SUBSCRIBER, "Broker");
client.send(msg);
client.close();
}
});
}
async _removeSubscriber(context, client) {
const { publishers } = context ?? {};
const subscriberIdentifier = getIdentifier({
name: context?.name,
ip: context?.ip
});
publishers.forEach((publisher) => {
const { name, ip } = publisher;
const identifier = getIdentifier({
name,
ip
});
const registeredPublisher = this._publisherMap.get(identifier);
if (!registeredPublisher) {
fileLog(`[${require_Action.ActionKind.EXIT_SUBSCRIBER}], ${identifier} does not exit `, "Broker", "warn");
return;
}
try {
fileLog(`[${require_Action.ActionKind.EXIT_SUBSCRIBER}], ${identifier} will exit `, "Broker", "INFO");
registeredPublisher.removeSubscriber(subscriberIdentifier);
this._clearTmpSubScriberRelation(identifier);
if (!registeredPublisher.hasSubscribes) this._publisherMap.delete(identifier);
if (!this.hasPublishers) this.exit();
} catch (err) {
const msg = error(err, require_Action.ActionKind.EXIT_SUBSCRIBER, "Broker");
client.send(msg);
client.close();
}
});
}
async _removePublisher(context, client) {
const { name, ip } = context ?? {};
const identifier = getIdentifier({
name,
ip
});
const publisher = this._publisherMap.get(identifier);
if (!publisher) {
fileLog(`[${require_Action.ActionKind.EXIT_PUBLISHER}]: ${identifier}} has not been added, this action will be ingored`, "Broker", "warn");
return;
}
try {
const { subscribers } = publisher;
subscribers.forEach((subscriber, subscriberIdentifier) => {
this._addTmpSubScriberRelation({
name: subscriberIdentifier,
client: subscriber
}, {
name: publisher.name,
ip: publisher.ip
});
fileLog(`[${require_Action.ActionKind.EXIT_PUBLISHER}]: ${identifier} is removing , subscriber: ${subscriberIdentifier} will be add tmpSubScriberRelation`, "Broker", "info");
});
this._publisherMap.delete(identifier);
fileLog(`[${require_Action.ActionKind.EXIT_PUBLISHER}]: ${identifier} is removed `, "Broker", "info");
if (!this.hasPublishers) {
fileLog(`[${require_Action.ActionKind.EXIT_PUBLISHER}]: _publisherMap is empty, all server will exit `, "Broker", "warn");
this.exit();
}
} catch (err) {
const msg = error(err, require_Action.ActionKind.EXIT_PUBLISHER, "Broker");
client.send(msg);
client.close();
}
}
async _addWebClient(context, client) {
const { name } = context ?? {};
const identifier = getIdentifier({ name });
if (this._webClientMap.has(identifier)) fileLog(`${identifier}} has been added, this action will override prev WebClient`, "Broker", "warn");
try {
this._webClientMap.set(identifier, client);
fileLog(`${identifier} adding WebClient Succeed`, "Broker", "info");
} catch (err) {
const msg = error(err, require_Action.ActionKind.ADD_WEB_CLIENT, "Broker");
client.send(msg);
client.close();
}
}
async _notifyWebClient(context, client) {
const { name, updateMode } = context ?? {};
const identifier = getIdentifier({ name });
const webClient = this._webClientMap.get(identifier);
if (!webClient) {
fileLog(`[${require_Action.ActionKind.NOTIFY_WEB_CLIENT}] ${identifier} has not been added, this action will be ignored`, "Broker", "warn");
return;
}
try {
const api = new ReloadWebClientAPI({
name,
updateMode
});
webClient.send(JSON.stringify(api));
fileLog(`[${require_Action.ActionKind.NOTIFY_WEB_CLIENT}] Notify ${name} WebClient Succeed`, "Broker", "info");
} catch (err) {
const msg = error(err, require_Action.ActionKind.NOTIFY_WEB_CLIENT, "Broker");
client.send(msg);
client.close();
}
}
_addTmpSubScriberRelation(subscriber, publisher) {
const publisherIdentifier = getIdentifier({
name: publisher.name,
ip: publisher.ip
});
const subscriberIdentifier = subscriber.name;
const shelter = this._tmpSubscriberShelter.get(publisherIdentifier);
if (!shelter) {
const map = /* @__PURE__ */ new Map();
map.set(subscriberIdentifier, subscriber);
this._tmpSubscriberShelter.set(publisherIdentifier, {
subscribers: map,
timestamp: Date.now()
});
fileLog(`[AddTmpSubscriberRelation] ${publisherIdentifier}'s subscriber has ${subscriberIdentifier} `, "Broker", "info");
return;
}
if (shelter.subscribers.get(subscriberIdentifier)) {
fileLog(`[AddTmpSubscriberRelation] ${publisherIdentifier} and ${subscriberIdentifier} relation has been added`, "Broker", "warn");
shelter.subscribers.set(subscriberIdentifier, subscriber);
shelter.timestamp = Date.now();
} else {
fileLog(`AddTmpSubscriberLog ${publisherIdentifier}'s shelter has been added, update shelter.subscribers ${subscriberIdentifier}`, "Broker", "warn");
shelter.subscribers.set(subscriberIdentifier, subscriber);
}
}
_getTmpSubScribers(publisherIdentifier) {
return this._tmpSubscriberShelter.get(publisherIdentifier)?.subscribers;
}
_consumeTmpSubScribers(publisher, tmpSubScribers) {
tmpSubScribers.forEach((tmpSubScriber, identifier) => {
fileLog(`notifyTmpSubScribers ${publisher.name} will be add a subscriber: ${identifier} `, "Broker", "warn");
publisher.addSubscriber(identifier, tmpSubScriber.client);
publisher.notifySubscriber(identifier, {
updateKind: UpdateKind.UPDATE_TYPE,
updateMode: require_Action.UpdateMode.PASSIVE,
updateSourcePaths: [publisher.name],
remoteTypeTarPath: publisher.remoteTypeTarPath,
name: publisher.name
});
});
}
_clearTmpSubScriberRelation(identifier) {
this._tmpSubscriberShelter.delete(identifier);
}
_clearTmpSubScriberRelations() {
this._tmpSubscriberShelter.clear();
}
_disconnect() {
this._publisherMap.forEach((publisher) => {
publisher.close();
});
}
_setSchedule() {
const rule = new node_schedule.default.RecurrenceRule();
if (Number(process.env["FEDERATION_SERVER_TEST"])) {
const interval = Number(process.env["FEDERATION_SERVER_TEST"]) / 1e3;
const second = [];
for (let i = 0; i < 60; i = i + interval) second.push(i);
rule.second = second;
} else {
rule.second = 0;
rule.hour = [
0,
3,
6,
9,
12,
15,
18
];
rule.minute = 0;
}
const serverTest = Number(process.env["FEDERATION_SERVER_TEST"]);
this._scheduleJob = node_schedule.default.scheduleJob(rule, () => {
this._tmpSubscriberShelter.forEach((tmpSubscriber, identifier) => {
fileLog(` _clearTmpSubScriberRelation ${identifier}, ${Date.now() - tmpSubscriber.timestamp >= (process.env["GARFISH_MODULE_SERVER_TEST"] ? serverTest : Broker.DEFAULT_WAITING_TIME)}`, "Broker", "info");
if (Date.now() - tmpSubscriber.timestamp >= (process.env["FEDERATION_SERVER_TEST"] ? serverTest : Broker.DEFAULT_WAITING_TIME)) this._clearTmpSubScriberRelation(identifier);
});
});
}
_clearSchedule() {
if (!this._scheduleJob) return;
this._scheduleJob.cancel();
this._scheduleJob = null;
}
_stopWhenSIGTERMOrSIGINT() {
process.on("SIGTERM", () => {
this.exit();
});
process.on("SIGINT", () => {
this.exit();
});
}
_handleUnexpectedExit() {
process.on("unhandledRejection", (error) => {
console.error("Unhandled Rejection Error: ", error);
fileLog(`Unhandled Rejection Error: ${error}`, "Broker", "fatal");
process.exit(1);
});
process.on("uncaughtException", (error) => {
console.error("Unhandled Exception Error: ", error);
fileLog(`Unhandled Rejection Error: ${error}`, "Broker", "fatal");
process.exit(1);
});
}
async start() {}
exit() {
const brokerExitLog = new BrokerExitLog();
this.broadcast(JSON.stringify(brokerExitLog));
this._disconnect();
this._clearSchedule();
this._clearTmpSubScriberRelations();
this._webSocketServer && this._webSocketServer.close();
this._secureWebSocketServer && this._secureWebSocketServer.close();
process.exit(0);
}
broadcast(message) {
fileLog(`[broadcast] exit info : ${JSON.stringify(message)}`, "Broker", "warn");
this._webSocketServer?.clients.forEach((client) => {
client.send(JSON.stringify(message));
});
this._secureWebSocketServer?.clients.forEach((client) => {
client.send(JSON.stringify(message));
});
}
};
//#endregion
Object.defineProperty(exports, 'APIKind', {
enumerable: true,
get: function () {
return APIKind;
}
});
Object.defineProperty(exports, 'Broker', {
enumerable: true,
get: function () {
return Broker;
}
});
Object.defineProperty(exports, 'LogKind', {
enumerable: true,
get: function () {
return LogKind;
}
});
Object.defineProperty(exports, 'UpdateKind', {
enumerable: true,
get: function () {
return UpdateKind;
}
});
Object.defineProperty(exports, 'fib', {
enumerable: true,
get: function () {
return fib;
}
});
Object.defineProperty(exports, 'fileLog', {
enumerable: true,
get: function () {
return fileLog;
}
});
Object.defineProperty(exports, 'getFreePort', {
enumerable: true,
get: function () {
return getFreePort;
}
});
Object.defineProperty(exports, 'getIPV4', {
enumerable: true,
get: function () {
return getIPV4;
}
});
Object.defineProperty(exports, 'getIdentifier', {
enumerable: true,
get: function () {
return getIdentifier;
}
});
Object.defineProperty(exports, 'logger', {
enumerable: true,
get: function () {
return logger;
}
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,166 @@
import { moduleFederationPlugin } from "@module-federation/sdk";
import ts from "typescript";
import { ChildProcess } from "child_process";
//#region \0rolldown/runtime.js
//#endregion
//#region src/core/interfaces/RemoteOptions.d.ts
interface RemoteOptions extends moduleFederationPlugin.DtsRemoteOptions {
moduleFederationConfig: moduleFederationPlugin.ModuleFederationPluginOptions;
context?: string;
implementation?: string;
hostRemoteTypesFolder?: string;
outputDir?: string;
}
//#endregion
//#region src/core/interfaces/TsConfigJson.d.ts
interface TsConfigJson {
extends?: string;
compilerOptions?: ts.CompilerOptions;
exclude?: string[];
include?: string[];
files?: string[];
}
//#endregion
//#region src/core/configurations/remotePlugin.d.ts
declare const retrieveRemoteConfig: (options: RemoteOptions) => {
tsConfig: TsConfigJson;
mapComponentsToExpose: Record<string, string>;
remoteOptions: Required<RemoteOptions>;
};
//#endregion
//#region src/core/interfaces/HostOptions.d.ts
interface HostOptions extends moduleFederationPlugin.DtsHostOptions {
moduleFederationConfig: moduleFederationPlugin.ModuleFederationPluginOptions;
context?: string;
implementation?: string;
runtimePkgs?: string[];
}
interface RemoteInfo {
name: string;
url: string;
alias: string;
zipUrl?: string;
apiTypeUrl?: string;
}
//#endregion
//#region src/core/interfaces/DTSManagerOptions.d.ts
interface DTSManagerOptions {
remote?: RemoteOptions;
host?: HostOptions;
extraOptions?: Record<string, any>;
displayErrorInTerminal?: moduleFederationPlugin.PluginDtsOptions['displayErrorInTerminal'];
}
//#endregion
//#region src/server/constant.d.ts
declare const enum UpdateMode {
POSITIVE = "POSITIVE",
PASSIVE = "PASSIVE"
}
//#endregion
//#region src/core/lib/DTSManager.d.ts
interface UpdateTypesOptions {
updateMode: UpdateMode;
remoteName?: string;
remoteTarPath?: string;
remoteInfo?: RemoteInfo;
once?: boolean;
}
declare class DTSManager {
options: DTSManagerOptions;
runtimePkgs: string[];
remoteAliasMap: Record<string, Required<RemoteInfo>>;
loadedRemoteAPIAlias: Set<string>;
extraOptions: Record<string, any>;
updatedRemoteInfos: Record<string, Required<RemoteInfo>>;
constructor(options: DTSManagerOptions);
generateAPITypes(mapComponentsToExpose: Record<string, string>): string;
extractRemoteTypes(options: ReturnType<typeof retrieveRemoteConfig>): Promise<void>;
generateTypes(): Promise<void>;
requestRemoteManifest(remoteInfo: RemoteInfo, hostOptions: Required<HostOptions>): Promise<Required<RemoteInfo>>;
consumeTargetRemotes(hostOptions: Required<HostOptions>, remoteInfo: Required<RemoteInfo>): Promise<[string, string]>;
downloadAPITypes(remoteInfo: Required<RemoteInfo>, destinationPath: string, hostOptions: Required<HostOptions>): Promise<boolean>;
consumeAPITypes(hostOptions: Required<HostOptions>): void;
consumeArchiveTypes(options: HostOptions): Promise<{
hostOptions: Required<HostOptions>;
downloadPromisesResult: PromiseSettledResult<[string, string]>[];
}>;
consumeTypes(): Promise<void>;
updateTypes(options: UpdateTypesOptions): Promise<void>;
}
//#endregion
//#region src/core/rpc/expose-rpc.d.ts
declare function exposeRpc(fn: (...args: any[]) => any): void;
//#endregion
//#region src/core/rpc/types.d.ts
declare enum RpcGMCallTypes {
CALL = "mf_call",
RESOLVE = "mf_resolve",
REJECT = "mf_reject",
EXIT = "mf_exit"
}
interface RpcCallMessage {
type: RpcGMCallTypes.CALL;
id: string;
args: unknown[];
}
interface RpcResolveMessage {
type: RpcGMCallTypes.RESOLVE;
id: string;
value: unknown;
}
interface RpcRejectMessage {
type: RpcGMCallTypes.REJECT;
id: string;
error: unknown;
}
interface RpcExitMessage {
type: RpcGMCallTypes.EXIT;
id: string;
}
type RpcMessage = RpcCallMessage | RpcResolveMessage | RpcRejectMessage | RpcExitMessage;
type RpcMethod = (...args: any[]) => any;
type RpcRemoteMethod<T extends RpcMethod> = T extends ((...args: infer A) => infer R) ? R extends Promise<any> ? (...args: A) => R : (...args: A) => Promise<R> : (...args: unknown[]) => Promise<unknown>;
//#endregion
//#region src/core/rpc/wrap-rpc.d.ts
interface WrapRpcOptions {
id: string;
once?: boolean;
}
declare function wrapRpc<T extends (...args: any[]) => any>(childProcess: ChildProcess, options: WrapRpcOptions): RpcRemoteMethod<T>;
//#endregion
//#region src/core/rpc/rpc-worker.d.ts
interface RpcWorkerBase {
connect(...args: unknown[]): any;
terminate(): void;
readonly connected: boolean;
readonly id: string;
readonly process: ChildProcess | undefined;
}
type RpcWorker<T extends RpcMethod = RpcMethod> = RpcWorkerBase & RpcRemoteMethod<T>;
declare function createRpcWorker<T extends RpcMethod>(modulePath: string, data: unknown, memoryLimit?: number, once?: boolean): RpcWorker<T>;
declare function getRpcWorkerData(): unknown;
//#endregion
//#region src/core/rpc/rpc-error.d.ts
declare class RpcExitError extends Error {
readonly code?: string | number | null;
readonly signal?: string | null;
constructor(message: string, code?: string | number | null, signal?: string | null);
}
declare namespace index_d_exports {
export { RpcCallMessage, RpcExitError, RpcGMCallTypes, RpcMessage, RpcMethod, RpcRejectMessage, RpcRemoteMethod, RpcResolveMessage, RpcWorker, createRpcWorker, exposeRpc, getRpcWorkerData, wrapRpc };
}
//#endregion
//#region src/core/lib/DtsWorker.d.ts
type DtsWorkerOptions = DTSManagerOptions;
declare class DtsWorker {
rpcWorker: RpcWorker<RpcMethod>;
private _options;
private _res;
constructor(options: DtsWorkerOptions);
removeUnSerializationOptions(): void;
get controlledPromise(): ReturnType<DTSManager['generateTypes']>;
exit(): void;
}
//#endregion
export { DTSManagerOptions as a, retrieveRemoteConfig as c, DTSManager as i, TsConfigJson as l, DtsWorkerOptions as n, HostOptions as o, index_d_exports as r, RemoteInfo as s, DtsWorker as t, RemoteOptions as u };

View File

@@ -0,0 +1 @@
# @module-federation/dts-plugin

View File

@@ -0,0 +1,42 @@
import { a as DTSManagerOptions, i as DTSManager, l as TsConfigJson, o as HostOptions, s as RemoteInfo, u as RemoteOptions } from "./DtsWorker-Dtem3-FM.js";
import { moduleFederationPlugin } from "@module-federation/sdk";
//#region src/core/configurations/hostPlugin.d.ts
declare const retrieveHostConfig: (options: HostOptions) => {
hostOptions: Required<HostOptions>;
mapRemotesToDownload: Record<string, RemoteInfo>;
};
//#endregion
//#region src/core/lib/utils.d.ts
declare function getDTSManagerConstructor(implementation?: string): typeof DTSManager;
declare const validateOptions: (options: HostOptions) => void;
declare function retrieveTypesAssetsInfo(options: RemoteOptions): {
apiTypesPath: string;
zipTypesPath: string;
zipName: string;
apiFileName: string;
};
declare const isTSProject: (dtsOptions: moduleFederationPlugin.ModuleFederationPluginOptions["dts"], context?: string) => boolean;
//#endregion
//#region src/core/lib/typeScriptCompiler.d.ts
declare const retrieveMfTypesPath: (tsConfig: TsConfigJson, remoteOptions: Required<RemoteOptions>) => string;
declare const retrieveOriginalOutDir: (tsConfig: TsConfigJson, remoteOptions: Required<RemoteOptions>) => string;
//#endregion
//#region src/core/lib/archiveHandler.d.ts
declare const retrieveTypesZipPath: (mfTypesPath: string, remoteOptions: Required<RemoteOptions>) => string;
//#endregion
//#region src/core/lib/generateTypes.d.ts
declare function generateTypes(options: DTSManagerOptions): Promise<void>;
//#endregion
//#region src/core/lib/generateTypesInChildProcess.d.ts
declare function generateTypesInChildProcess(options: DTSManagerOptions): Promise<void>;
//#endregion
//#region src/core/lib/consumeTypes.d.ts
declare function consumeTypes(options: DTSManagerOptions): Promise<void>;
//#endregion
//#region src/core/constant.d.ts
declare const REMOTE_ALIAS_IDENTIFIER = "REMOTE_ALIAS_IDENTIFIER";
declare const REMOTE_API_TYPES_FILE_NAME = "apis.d.ts";
declare const HOST_API_TYPES_FILE_NAME = "index.d.ts";
//#endregion
export { generateTypesInChildProcess as a, retrieveMfTypesPath as c, isTSProject as d, retrieveTypesAssetsInfo as f, consumeTypes as i, retrieveOriginalOutDir as l, retrieveHostConfig as m, REMOTE_ALIAS_IDENTIFIER as n, generateTypes as o, validateOptions as p, REMOTE_API_TYPES_FILE_NAME as r, retrieveTypesZipPath as s, HOST_API_TYPES_FILE_NAME as t, getDTSManagerConstructor as u };

View File

@@ -0,0 +1,241 @@
const require_Action = require('./Action-CzhPMw2i.js');
const require_expose_rpc = require('./expose-rpc-mEaCWCcd.js');
let path = require("path");
path = require_Action.__toESM(path);
let crypto = require("crypto");
let child_process = require("child_process");
child_process = require_Action.__toESM(child_process);
let url = require("url");
let process$1 = require("process");
process$1 = require_Action.__toESM(process$1);
//#region src/core/rpc/rpc-error.ts
var RpcExitError = class extends Error {
constructor(message, code, signal) {
super(message);
this.code = code;
this.signal = signal;
this.name = "RpcExitError";
}
};
//#endregion
//#region src/core/rpc/wrap-rpc.ts
function createControlledPromise() {
let resolve = () => void 0;
let reject = () => void 0;
return {
promise: new Promise((aResolve, aReject) => {
resolve = aResolve;
reject = aReject;
}),
resolve,
reject
};
}
function wrapRpc(childProcess, options) {
return (async (...args) => {
if (!childProcess.send) throw new Error(`Process ${childProcess.pid} doesn't have IPC channels`);
else if (!childProcess.connected) throw new Error(`Process ${childProcess.pid} doesn't have open IPC channels`);
const { id, once } = options;
const { promise: resultPromise, resolve: resolveResult, reject: rejectResult } = createControlledPromise();
const { promise: sendPromise, resolve: resolveSend, reject: rejectSend } = createControlledPromise();
const handleMessage = (message) => {
if (message?.id === id) {
if (message.type === require_expose_rpc.RpcGMCallTypes.RESOLVE) resolveResult(message.value);
else if (message.type === require_expose_rpc.RpcGMCallTypes.REJECT) rejectResult(message.error);
}
if (once && childProcess?.kill) childProcess.kill("SIGTERM");
};
const handleClose = (code, signal) => {
rejectResult(new RpcExitError(code ? `Process ${childProcess.pid} exited with code ${code}${signal ? ` [${signal}]` : ""}` : `Process ${childProcess.pid} exited${signal ? ` [${signal}]` : ""}`, code, signal));
removeHandlers();
};
const removeHandlers = () => {
childProcess.off("message", handleMessage);
childProcess.off("close", handleClose);
};
if (once) childProcess.once("message", handleMessage);
else childProcess.on("message", handleMessage);
childProcess.on("close", handleClose);
childProcess.send({
type: require_expose_rpc.RpcGMCallTypes.CALL,
id,
args
}, (error) => {
if (error) {
rejectSend(error);
removeHandlers();
} else resolveSend(void 0);
});
return sendPromise.then(() => resultPromise);
});
}
//#endregion
//#region src/core/rpc/rpc-worker.ts
const FEDERATION_WORKER_DATA_ENV_KEY = "VMOK_WORKER_DATA_ENV";
function createRpcWorker(modulePath, data, memoryLimit, once) {
const options = {
env: {
...process$1.env,
[FEDERATION_WORKER_DATA_ENV_KEY]: JSON.stringify(data || {})
},
stdio: [
"inherit",
"inherit",
"inherit",
"ipc"
],
serialization: "advanced"
};
if (memoryLimit) options.execArgv = [`--max-old-space-size=${memoryLimit}`];
let childProcess, remoteMethod;
const id = (0, crypto.randomUUID)();
return {
connect(...args) {
if (childProcess && !childProcess.connected) {
childProcess.send({
type: require_expose_rpc.RpcGMCallTypes.EXIT,
id
});
childProcess = void 0;
remoteMethod = void 0;
}
if (!childProcess?.connected) {
childProcess = child_process.fork(modulePath, options);
remoteMethod = wrapRpc(childProcess, {
id,
once
});
}
if (!remoteMethod) return Promise.reject(/* @__PURE__ */ new Error("Worker is not connected - cannot perform RPC."));
return remoteMethod(...args);
},
terminate() {
try {
if (childProcess.connected) childProcess.send({
type: require_expose_rpc.RpcGMCallTypes.EXIT,
id
}, (err) => {
if (err) console.error("Error sending message:", err);
});
} catch (error) {
if (error.code === "EPIPE") console.error("Pipe closed before message could be sent:", error);
else console.error("Unexpected error:", error);
}
childProcess = void 0;
remoteMethod = void 0;
},
get connected() {
return Boolean(childProcess?.connected);
},
get process() {
return childProcess;
},
get id() {
return id;
}
};
}
function getRpcWorkerData() {
return JSON.parse(process$1.env[FEDERATION_WORKER_DATA_ENV_KEY] || "{}");
}
//#endregion
//#region src/core/rpc/index.ts
var rpc_exports = /* @__PURE__ */ require_Action.__exportAll({
RpcExitError: () => RpcExitError,
RpcGMCallTypes: () => require_expose_rpc.RpcGMCallTypes,
createRpcWorker: () => createRpcWorker,
exposeRpc: () => require_expose_rpc.exposeRpc,
getRpcWorkerData: () => getRpcWorkerData,
wrapRpc: () => wrapRpc
});
//#endregion
//#region src/core/lib/DtsWorker.ts
const __filename$1 = (0, url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
const __dirname$1 = path.default.dirname(__filename$1);
const __extname = path.default.extname(__filename$1);
var DtsWorker = class {
constructor(options) {
this._options = require_expose_rpc.cloneDeepOptions(options);
this.removeUnSerializationOptions();
this.rpcWorker = createRpcWorker(path.default.resolve(__dirname$1, `./fork-generate-dts${__extname}`), {}, void 0, true);
this._res = this.rpcWorker.connect(this._options);
}
removeUnSerializationOptions() {
if (this._options.remote?.moduleFederationConfig?.manifest) delete this._options.remote?.moduleFederationConfig?.manifest;
if (this._options.host?.moduleFederationConfig?.manifest) delete this._options.host?.moduleFederationConfig?.manifest;
}
get controlledPromise() {
const ensureChildProcessExit = () => {
try {
const pid = this.rpcWorker.process?.pid;
const rootPid = process.pid;
if (pid && rootPid !== pid) process.kill(pid, 0);
} catch (error) {
if (require_expose_rpc.isDebugMode()) console.error(error);
}
};
return Promise.resolve(this._res).then(() => {
this.exit();
ensureChildProcessExit();
}).catch((err) => {
if (require_expose_rpc.isDebugMode()) console.error(err);
ensureChildProcessExit();
});
}
exit() {
try {
this.rpcWorker?.terminate();
} catch (err) {
if (require_expose_rpc.isDebugMode()) console.error(err);
}
}
};
//#endregion
//#region src/core/lib/generateTypesInChildProcess.ts
async function generateTypesInChildProcess(options) {
return new DtsWorker(options).controlledPromise;
}
//#endregion
//#region src/core/lib/consumeTypes.ts
async function consumeTypes(options) {
await new (require_expose_rpc.getDTSManagerConstructor(options.host?.implementation))(options).consumeTypes();
}
//#endregion
Object.defineProperty(exports, 'DtsWorker', {
enumerable: true,
get: function () {
return DtsWorker;
}
});
Object.defineProperty(exports, 'consumeTypes', {
enumerable: true,
get: function () {
return consumeTypes;
}
});
Object.defineProperty(exports, 'createRpcWorker', {
enumerable: true,
get: function () {
return createRpcWorker;
}
});
Object.defineProperty(exports, 'generateTypesInChildProcess', {
enumerable: true,
get: function () {
return generateTypesInChildProcess;
}
});
Object.defineProperty(exports, 'rpc_exports', {
enumerable: true,
get: function () {
return rpc_exports;
}
});

View File

@@ -0,0 +1,3 @@
import { a as DTSManagerOptions, c as retrieveRemoteConfig, i as DTSManager, o as HostOptions, r as index_d_exports, t as DtsWorker, u as RemoteOptions } from "./DtsWorker-Dtem3-FM.js";
import { a as generateTypesInChildProcess, c as retrieveMfTypesPath, d as isTSProject, f as retrieveTypesAssetsInfo, i as consumeTypes, l as retrieveOriginalOutDir, m as retrieveHostConfig, n as REMOTE_ALIAS_IDENTIFIER, o as generateTypes, p as validateOptions, r as REMOTE_API_TYPES_FILE_NAME, s as retrieveTypesZipPath, t as HOST_API_TYPES_FILE_NAME, u as getDTSManagerConstructor } from "./constant-BwEkyidO.js";
export { DTSManager, type DTSManagerOptions, DtsWorker, HOST_API_TYPES_FILE_NAME, type HostOptions, REMOTE_ALIAS_IDENTIFIER, REMOTE_API_TYPES_FILE_NAME, type RemoteOptions, consumeTypes, generateTypes, generateTypesInChildProcess, getDTSManagerConstructor, isTSProject, retrieveHostConfig, retrieveMfTypesPath, retrieveOriginalOutDir, retrieveRemoteConfig, retrieveTypesAssetsInfo, retrieveTypesZipPath, index_d_exports as rpc, validateOptions };

View File

@@ -0,0 +1,28 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
require('./Broker-DRFgFvXI.js');
const require_expose_rpc = require('./expose-rpc-mEaCWCcd.js');
const require_consumeTypes = require('./consumeTypes-CFK17Cck.js');
exports.DTSManager = require_expose_rpc.DTSManager;
exports.DtsWorker = require_consumeTypes.DtsWorker;
exports.HOST_API_TYPES_FILE_NAME = require_expose_rpc.HOST_API_TYPES_FILE_NAME;
exports.REMOTE_ALIAS_IDENTIFIER = require_expose_rpc.REMOTE_ALIAS_IDENTIFIER;
exports.REMOTE_API_TYPES_FILE_NAME = require_expose_rpc.REMOTE_API_TYPES_FILE_NAME;
exports.consumeTypes = require_consumeTypes.consumeTypes;
exports.generateTypes = require_expose_rpc.generateTypes;
exports.generateTypesInChildProcess = require_consumeTypes.generateTypesInChildProcess;
exports.getDTSManagerConstructor = require_expose_rpc.getDTSManagerConstructor;
exports.isTSProject = require_expose_rpc.isTSProject;
exports.retrieveHostConfig = require_expose_rpc.retrieveHostConfig;
exports.retrieveMfTypesPath = require_expose_rpc.retrieveMfTypesPath;
exports.retrieveOriginalOutDir = require_expose_rpc.retrieveOriginalOutDir;
exports.retrieveRemoteConfig = require_expose_rpc.retrieveRemoteConfig;
exports.retrieveTypesAssetsInfo = require_expose_rpc.retrieveTypesAssetsInfo;
exports.retrieveTypesZipPath = require_expose_rpc.retrieveTypesZipPath;
Object.defineProperty(exports, 'rpc', {
enumerable: true,
get: function () {
return require_consumeTypes.rpc_exports;
}
});
exports.validateOptions = require_expose_rpc.validateOptions;

View File

@@ -0,0 +1,766 @@
import { CreateLinkHookReturnDom, CreateScriptHookReturn, GlobalModuleInfo, Manifest, Module, ModuleInfo, RemoteEntryType, RemoteWithEntry, RemoteWithVersion, TreeShakingStatus } from "@module-federation/sdk";
//#region ../runtime-core/dist/utils/hooks/syncHook.d.ts
//#region src/utils/hooks/syncHook.d.ts
type Callback<T, K> = (...args: ArgsType<T>) => K;
type ArgsType<T> = T extends Array<any> ? T : Array<any>;
declare class SyncHook<T, K> {
type: string;
listeners: Set<Callback<T, K>>;
constructor(type?: string);
on(fn: Callback<T, K>): void;
once(fn: Callback<T, K>): void;
emit(...data: ArgsType<T>): void | K | Promise<any>;
remove(fn: Callback<T, K>): void;
removeAll(): void;
} //#endregion
//#endregion
//#region ../runtime-core/dist/utils/hooks/asyncHook.d.ts
//#region src/utils/hooks/asyncHook.d.ts
type CallbackReturnType$1 = void | false | Promise<void | false>;
declare class AsyncHook<T, ExternalEmitReturnType = CallbackReturnType$1> extends SyncHook<T, ExternalEmitReturnType> {
emit(...data: ArgsType<T>): Promise<void | false | ExternalEmitReturnType>;
} //#endregion
//#endregion
//#region ../runtime-core/dist/utils/hooks/syncWaterfallHook.d.ts
//#region src/utils/hooks/syncWaterfallHook.d.ts
declare class SyncWaterfallHook<T extends Record<string, any>> extends SyncHook<[T], T | void> {
onerror: (errMsg: string | Error | unknown) => void;
constructor(type: string);
emit(data: T): T;
} //#endregion
//#endregion
//#region ../runtime-core/dist/utils/hooks/asyncWaterfallHooks.d.ts
//#region src/utils/hooks/asyncWaterfallHooks.d.ts
type CallbackReturnType<T> = T | void | Promise<T | void>;
declare class AsyncWaterfallHook<T extends object> extends SyncHook<[T], CallbackReturnType<T>> {
onerror: (errMsg: string | Error | unknown) => void;
constructor(type: string);
emit(data: T): Promise<T>;
} //#endregion
//#endregion
//#region ../runtime-core/dist/utils/hooks/pluginSystem.d.ts
//#region src/utils/hooks/pluginSystem.d.ts
type Plugin<T extends Record<string, any>> = { [k in keyof T]?: Parameters<T[k]['on']>[0] } & {
name: string;
version?: string;
apply?: (instance: ModuleFederation) => void;
};
declare class PluginSystem<T extends Record<string, any>> {
lifecycle: T;
lifecycleKeys: Array<keyof T>;
registerPlugins: Record<string, Plugin<T>>;
constructor(lifecycle: T);
applyPlugin(plugin: Plugin<T>, instance: ModuleFederation): void;
removePlugin(pluginName: string): void;
} //#endregion
//#endregion
//#region ../runtime-core/dist/type/config.d.ts
//#region src/type/config.d.ts
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>;
interface RemoteInfoCommon {
alias?: string;
shareScope?: string | string[];
type?: RemoteEntryType;
entryGlobalName?: string;
}
type Remote = (RemoteWithEntry | RemoteWithVersion) & RemoteInfoCommon;
interface RemoteInfo {
alias?: string;
name: string;
version?: string;
buildVersion?: string;
entry: string;
type: RemoteEntryType;
entryGlobalName: string;
shareScope: string | string[];
}
interface SharedConfig {
singleton?: boolean;
requiredVersion: false | string;
eager?: boolean;
strictVersion?: boolean;
layer?: string | null;
}
type TreeShakingArgs = {
usedExports?: string[];
get?: SharedGetter;
lib?: () => Module;
status?: TreeShakingStatus;
mode?: 'server-calc' | 'runtime-infer';
loading?: null | Promise<any>;
loaded?: boolean;
useIn?: Array<string>;
};
type SharedBaseArgs = {
version?: string;
shareConfig?: SharedConfig;
scope?: string | Array<string>;
deps?: Array<string>;
strategy?: 'version-first' | 'loaded-first';
loaded?: boolean;
treeShaking?: TreeShakingArgs;
};
type SharedGetter = (() => () => Module) | (() => Promise<() => Module>);
type ShareArgs = (SharedBaseArgs & {
get: SharedGetter;
}) | (SharedBaseArgs & {
lib: () => Module;
}) | SharedBaseArgs;
type ShareStrategy = 'version-first' | 'loaded-first';
type Shared = {
version: string;
get: SharedGetter;
shareConfig: SharedConfig;
scope: Array<string>;
useIn: Array<string>;
from: string;
deps: Array<string>;
lib?: () => Module;
loaded?: boolean;
loading?: null | Promise<any>;
eager?: boolean;
/**
* @deprecated set in initOptions.shareStrategy instead
*/
strategy: ShareStrategy;
treeShaking?: TreeShakingArgs;
};
type ShareScopeMap = {
[scope: string]: {
[pkgName: string]: {
[sharedVersion: string]: Shared;
};
};
};
type GlobalShareScopeMap = {
[instanceName: string]: ShareScopeMap;
};
type ShareInfos = {
[pkgName: string]: Shared[];
};
interface Options {
id?: string;
name: string;
version?: string;
remotes: Array<Remote>;
shared: ShareInfos;
plugins: Array<ModuleFederationRuntimePlugin>;
inBrowser: boolean;
shareStrategy?: ShareStrategy;
}
type UserOptions = Omit<Optional<Options, 'plugins'>, 'shared' | 'inBrowser'> & {
shared?: {
[pkgName: string]: ShareArgs | ShareArgs[];
};
};
type RemoteEntryInitOptions = {
version: string;
shareScopeMap?: ShareScopeMap;
shareScopeKeys: string | string[];
};
type InitTokens = Record<string, Record<string, any>>;
type InitScope = InitTokens[];
type CallFrom = 'build' | 'runtime';
type RemoteEntryExports = {
get: (id: string) => () => Promise<Module>;
init: (shareScope: ShareScopeMap[string], initScope?: InitScope, remoteEntryInitOPtions?: RemoteEntryInitOptions) => void | Promise<void>;
}; //#endregion
//#endregion
//#region ../runtime-core/dist/type/preload.d.ts
//#region src/type/preload.d.ts
type depsPreloadArg = Omit<PreloadRemoteArgs, 'depsRemote'>;
interface PreloadRemoteArgs {
nameOrAlias: string;
exposes?: Array<string>;
resourceCategory?: 'all' | 'sync';
share?: boolean;
depsRemote?: boolean | Array<depsPreloadArg>;
filter?: (assetUrl: string) => boolean;
}
type PreloadConfig = PreloadRemoteArgs;
type PreloadOptions = Array<{
remote: Remote;
preloadConfig: PreloadConfig;
}>;
type ResourceLoadInitiator = 'loadRemote' | 'preloadRemote';
type ResourceLoadType = 'manifest' | 'remoteEntry' | 'js' | 'css';
interface ResourceLoadContext {
initiator: ResourceLoadInitiator;
id: string;
resourceType: ResourceLoadType;
url?: string;
}
type PreloadAssetStatus = 'success' | 'error' | 'timeout' | 'cached';
interface PreloadAssetResult {
url: string;
status: PreloadAssetStatus;
resourceType: ResourceLoadType;
initiator: ResourceLoadInitiator;
id: string;
error?: unknown;
}
interface PreloadRemoteResult {
remote: Remote;
remoteInfo: RemoteInfo;
preloadConfig: PreloadConfig;
id: string;
results: PreloadAssetResult[];
}
type EntryAssets = {
name: string;
url: string;
moduleInfo: RemoteInfo;
};
interface PreloadAssets {
cssAssets: Array<string>;
jsAssetsWithoutEntry: Array<string>;
entryAssets: Array<EntryAssets>;
} //#endregion
//#endregion
//#region ../runtime-core/dist/remote/index.d.ts
//#region src/remote/index.d.ts
interface LoadRemoteMatch {
id: string;
pkgNameOrAlias: string;
expose: string;
remote: Remote;
options: Options;
origin: ModuleFederation;
remoteInfo: RemoteInfo;
remoteSnapshot?: ModuleInfo;
}
declare class RemoteHandler {
host: ModuleFederation;
idToRemoteMap: Record<string, {
name: string;
expose: string;
}>;
hooks: PluginSystem<{
beforeRegisterRemote: SyncWaterfallHook<{
remote: Remote;
origin: ModuleFederation;
}>;
registerRemote: SyncWaterfallHook<{
remote: Remote;
origin: ModuleFederation;
}>;
beforeRequest: AsyncWaterfallHook<{
id: string;
options: Options;
origin: ModuleFederation;
}>;
afterMatchRemote: AsyncHook<[{
id: string;
options: Options;
remote?: Remote;
expose?: string;
remoteInfo?: RemoteInfo;
error?: unknown;
origin: ModuleFederation;
}], void>;
onLoad: AsyncHook<[{
id: string;
expose: string;
pkgNameOrAlias: string;
remote: Remote;
options: ModuleOptions;
origin: ModuleFederation;
exposeModule: any;
exposeModuleFactory: any;
moduleInstance: Module$1;
}], unknown>;
afterLoadRemote: AsyncHook<[{
id: string;
expose?: string;
remote?: RemoteInfo;
options?: {
loadFactory?: boolean;
from?: CallFrom;
};
error?: unknown;
recovered?: boolean;
origin: ModuleFederation;
}], void>;
handlePreloadModule: SyncHook<[{
id: string;
name: string;
remote: Remote;
remoteSnapshot: ModuleInfo;
preloadConfig: PreloadRemoteArgs;
origin: ModuleFederation;
}], void>;
errorLoadRemote: AsyncHook<[{
id: string;
error: unknown;
options?: any;
from: CallFrom;
lifecycle: "beforeRequest" | "beforeLoadShare" | "afterResolve" | "onLoad";
remote?: RemoteInfo;
expose?: string;
origin: ModuleFederation;
}], unknown>;
beforePreloadRemote: AsyncHook<[{
preloadOps: Array<PreloadRemoteArgs>;
options: Options;
origin: ModuleFederation;
}], false | void | Promise<false | void>>;
generatePreloadAssets: AsyncHook<[{
origin: ModuleFederation;
preloadOptions: PreloadOptions[number];
remote: Remote;
remoteInfo: RemoteInfo;
remoteSnapshot: ModuleInfo;
globalSnapshot: GlobalModuleInfo;
}], Promise<PreloadAssets>>;
afterPreloadRemote: AsyncHook<[{
preloadOps: Array<PreloadRemoteArgs>;
options: Options;
origin: ModuleFederation;
results: PreloadRemoteResult[];
error?: unknown;
}], false | void | Promise<false | void>>;
loadEntry: AsyncHook<[{
origin: ModuleFederation;
loaderHook: ModuleFederation["loaderHook"];
remoteInfo: RemoteInfo;
remoteEntryExports?: RemoteEntryExports;
}], void | RemoteEntryExports | Promise<void | RemoteEntryExports>>;
}>;
constructor(host: ModuleFederation);
formatAndRegisterRemote(globalOptions: Options, userOptions: UserOptions): Remote[];
setIdToRemoteMap(id: string, remoteMatchInfo: LoadRemoteMatch): void;
loadRemote<T>(id: string, options?: {
loadFactory?: boolean;
from: CallFrom;
}): Promise<T | null>;
preloadRemote(preloadOptions: Array<PreloadRemoteArgs>): Promise<void>;
registerRemotes(remotes: Remote[], options?: {
force?: boolean;
}): void;
getRemoteModuleAndOptions(options: {
id: string;
}): Promise<{
module: Module$1;
moduleOptions: ModuleOptions;
remoteMatchInfo: LoadRemoteMatch;
}>;
registerRemote(remote: Remote, targetRemotes: Remote[], options?: {
force?: boolean;
}): void;
private removeRemote;
} //#endregion
//#endregion
//#region ../runtime-core/dist/shared/index.d.ts
//#region src/shared/index.d.ts
declare class SharedHandler {
host: ModuleFederation;
shareScopeMap: ShareScopeMap;
hooks: PluginSystem<{
beforeRegisterShare: SyncWaterfallHook<{
pkgName: string;
shared: Shared;
origin: ModuleFederation;
}>;
afterResolve: AsyncWaterfallHook<LoadRemoteMatch>;
beforeLoadShare: AsyncWaterfallHook<{
pkgName: string;
shareInfo?: Shared;
shared: Options["shared"];
origin: ModuleFederation;
}>;
loadShare: AsyncHook<[ModuleFederation, string, ShareInfos], false | void | Promise<false | void>>;
afterLoadShare: SyncHook<[{
pkgName: string;
shareInfo?: Partial<Shared>;
selectedShared?: Partial<Shared>;
shared: Options["shared"];
shareScopeMap: ShareScopeMap;
lifecycle: "loadShare" | "loadShareSync";
origin: ModuleFederation;
}], void>;
errorLoadShare: SyncHook<[{
pkgName: string;
shareInfo?: Partial<Shared>;
shared: Options["shared"];
shareScopeMap: ShareScopeMap;
lifecycle: "loadShare" | "loadShareSync";
origin: ModuleFederation;
error?: unknown;
recovered?: boolean;
}], void>;
resolveShare: SyncWaterfallHook<{
shareScopeMap: ShareScopeMap;
scope: string;
pkgName: string;
version: string;
shareInfo: Shared;
GlobalFederation: Federation;
resolver: () => {
shared: Shared;
useTreesShaking: boolean;
} | undefined;
}>;
initContainerShareScopeMap: SyncWaterfallHook<{
shareScope: ShareScopeMap[string];
options: Options;
origin: ModuleFederation;
scopeName: string;
hostShareScopeMap?: ShareScopeMap;
}>;
}>;
initTokens: InitTokens;
constructor(host: ModuleFederation);
private emitAfterLoadShare;
private emitErrorLoadShare;
registerShared(globalOptions: Options, userOptions: UserOptions): {
newShareInfos: ShareInfos;
allShareInfos: {
[pkgName: string]: Shared[];
};
};
loadShare<T>(pkgName: string, extraOptions?: {
customShareInfo?: Partial<Shared>;
resolver?: (sharedOptions: ShareInfos[string]) => Shared;
}): Promise<false | (() => T | undefined)>;
/**
* This function initializes the sharing sequence (executed only once per share scope).
* It accepts one argument, the name of the share scope.
* If the share scope does not exist, it creates one.
*/
initializeSharing(shareScopeName?: string, extraOptions?: {
initScope?: InitScope;
from?: CallFrom;
strategy?: ShareStrategy;
}): Array<Promise<void>>;
loadShareSync<T>(pkgName: string, extraOptions?: {
from?: 'build' | 'runtime';
customShareInfo?: Partial<Shared>;
resolver?: (sharedOptions: ShareInfos[string]) => Shared;
}): () => T | never;
initShareScopeMap(scopeName: string, shareScope: ShareScopeMap[string], extraOptions?: {
hostShareScopeMap?: ShareScopeMap;
}): void;
private setShared;
private _setGlobalShareScopeMap;
} //#endregion
//#endregion
//#region ../runtime-core/dist/type/plugin.d.ts
//#region src/type/plugin.d.ts
type CoreLifeCycle = ModuleFederation['hooks']['lifecycle'];
type CoreLifeCyclePartial = Partial<{ [k in keyof CoreLifeCycle]: Parameters<CoreLifeCycle[k]['on']>[0] }>;
type SnapshotLifeCycle = SnapshotHandler['hooks']['lifecycle'];
type SnapshotLifeCycleCyclePartial = Partial<{ [k in keyof SnapshotLifeCycle]: Parameters<SnapshotLifeCycle[k]['on']>[0] }>;
type ModuleLifeCycle = Module$1['host']['loaderHook']['lifecycle'];
type ModuleLifeCycleCyclePartial = Partial<{ [k in keyof ModuleLifeCycle]: Parameters<ModuleLifeCycle[k]['on']>[0] }>;
type ModuleBridgeLifeCycle = Module$1['host']['bridgeHook']['lifecycle'];
type ModuleBridgeLifeCycleCyclePartial = Partial<{ [k in keyof ModuleBridgeLifeCycle]: Parameters<ModuleBridgeLifeCycle[k]['on']>[0] }>;
type SharedLifeCycle = SharedHandler['hooks']['lifecycle'];
type SharedLifeCycleCyclePartial = Partial<{ [k in keyof SharedLifeCycle]: Parameters<SharedLifeCycle[k]['on']>[0] }>;
type RemoteLifeCycle = RemoteHandler['hooks']['lifecycle'];
type RemoteLifeCycleCyclePartial = Partial<{ [k in keyof RemoteLifeCycle]: Parameters<RemoteLifeCycle[k]['on']>[0] }>;
type ModuleFederationRuntimePlugin = CoreLifeCyclePartial & SnapshotLifeCycleCyclePartial & SharedLifeCycleCyclePartial & RemoteLifeCycleCyclePartial & ModuleLifeCycleCyclePartial & ModuleBridgeLifeCycleCyclePartial & {
name: string;
version?: string;
apply?: (instance: ModuleFederation) => void;
}; //#endregion
//#endregion
//#region ../runtime-core/dist/global.d.ts
//#region src/global.d.ts
interface Federation {
__GLOBAL_PLUGIN__: Array<ModuleFederationRuntimePlugin>;
__DEBUG_CONSTRUCTOR_VERSION__?: string;
moduleInfo: GlobalModuleInfo;
__DEBUG_CONSTRUCTOR__?: typeof ModuleFederation;
__INSTANCES__: Array<ModuleFederation>;
__SHARE__: GlobalShareScopeMap;
__MANIFEST_LOADING__: Record<string, Promise<ModuleInfo>>;
__PRELOADED_MAP__: Map<string, boolean>;
}
declare global {
var __FEDERATION__: Federation, __VMOK__: Federation, __GLOBAL_LOADING_REMOTE_ENTRY__: Record<string, undefined | Promise<RemoteEntryExports | void>>;
}
declare const getGlobalSnapshot: () => GlobalModuleInfo;
//#endregion
//#region ../runtime-core/dist/plugins/snapshot/SnapshotHandler.d.ts
//#region src/plugins/snapshot/SnapshotHandler.d.ts
declare class SnapshotHandler {
loadingHostSnapshot: Promise<GlobalModuleInfo | void> | null;
HostInstance: ModuleFederation;
manifestCache: Map<string, Manifest>;
hooks: PluginSystem<{
beforeLoadRemoteSnapshot: AsyncHook<[{
options: Options;
moduleInfo: Remote;
origin: ModuleFederation;
}], void>;
loadSnapshot: AsyncWaterfallHook<{
options: Options;
moduleInfo: Remote;
hostGlobalSnapshot: GlobalModuleInfo[string] | undefined;
globalSnapshot: ReturnType<typeof getGlobalSnapshot>;
remoteSnapshot?: GlobalModuleInfo[string] | undefined;
}>;
loadRemoteSnapshot: AsyncWaterfallHook<{
options: Options;
moduleInfo: Remote;
manifestJson?: Manifest;
manifestUrl?: string;
remoteSnapshot: ModuleInfo;
from: "global" | "manifest";
}>;
afterLoadSnapshot: AsyncWaterfallHook<{
id?: string;
host: ModuleFederation;
options: Options;
moduleInfo: Remote;
remoteSnapshot: ModuleInfo;
}>;
}>;
loaderHook: ModuleFederation['loaderHook'];
manifestLoading: Record<string, Promise<ModuleInfo>>;
constructor(HostInstance: ModuleFederation);
loadRemoteSnapshotInfo({
moduleInfo,
id,
initiator
}: {
moduleInfo: Remote;
id?: string;
initiator?: ResourceLoadInitiator;
}): Promise<{
remoteSnapshot: ModuleInfo;
globalSnapshot: GlobalModuleInfo;
}> | never;
getGlobalRemoteInfo(moduleInfo: Remote): {
hostGlobalSnapshot: ModuleInfo | undefined;
globalSnapshot: ReturnType<typeof getGlobalSnapshot>;
remoteSnapshot: GlobalModuleInfo[string] | undefined;
};
private getManifestJson;
private loadManifestSnapshot;
} //#endregion
//#endregion
//#region ../runtime-core/dist/utils/load.d.ts
//#region src/utils/load.d.ts
declare function getRemoteEntry(params: {
origin: ModuleFederation;
remoteInfo: RemoteInfo;
remoteEntryExports?: RemoteEntryExports | undefined;
getEntryUrl?: (url: string) => string;
_inErrorHandling?: boolean;
resourceContext?: ResourceLoadContext;
}): Promise<RemoteEntryExports | false | void>;
//#endregion
//#region ../runtime-core/dist/core.d.ts
//#region src/core.d.ts
declare class ModuleFederation {
options: Options;
hooks: PluginSystem<{
beforeInit: SyncWaterfallHook<{
userOptions: UserOptions;
options: Options;
origin: ModuleFederation;
/**
* @deprecated shareInfo will be removed soon, please use userOptions directly!
*/
shareInfo: ShareInfos;
}>;
init: SyncHook<[{
options: Options;
origin: ModuleFederation;
}], void>;
beforeInitContainer: AsyncWaterfallHook<{
shareScope: ShareScopeMap[string];
initScope: InitScope;
remoteEntryInitOptions: RemoteEntryInitOptions;
remoteInfo: RemoteInfo;
origin: ModuleFederation;
}>;
initContainer: AsyncWaterfallHook<{
shareScope: ShareScopeMap[string];
initScope: InitScope;
remoteEntryInitOptions: RemoteEntryInitOptions;
remoteInfo: RemoteInfo;
remoteEntryExports: RemoteEntryExports;
origin: ModuleFederation;
id?: string;
remoteSnapshot?: ModuleInfo;
}>;
}>;
version: string;
name: string;
moduleCache: Map<string, Module$1>;
snapshotHandler: SnapshotHandler;
sharedHandler: SharedHandler;
remoteHandler: RemoteHandler;
shareScopeMap: ShareScopeMap;
loaderHook: PluginSystem<{
getModuleInfo: SyncHook<[{
target: Record<string, any>;
key: any;
}], void | {
value: any | undefined;
key: string;
}>;
createScript: SyncHook<[{
url: string;
attrs?: Record<string, any>;
/**
* The producer(remote) info bound to this resource.
* Only present when the loader is invoked in a remote-related context
* (e.g. preloadRemote / loading remoteEntry).
*/
remoteInfo?: RemoteInfo;
resourceContext?: ResourceLoadContext;
}], CreateScriptHookReturn>;
createLink: SyncHook<[{
url: string;
attrs?: Record<string, any>;
/**
* The producer(remote) info bound to this resource.
* Only present when the loader is invoked in a remote-related context
* (e.g. preloadRemote / loading remoteEntry).
*/
remoteInfo?: RemoteInfo;
resourceContext?: ResourceLoadContext;
}], CreateLinkHookReturnDom>;
fetch: AsyncHook<[string, RequestInit, (RemoteInfo | undefined)?, (ResourceLoadContext | undefined)?], false | void | Promise<Response>>;
loadEntryError: AsyncHook<[{
getRemoteEntry: typeof getRemoteEntry;
origin: ModuleFederation;
remoteInfo: RemoteInfo;
remoteEntryExports?: RemoteEntryExports | undefined;
globalLoading: Record<string, Promise<void | RemoteEntryExports> | undefined>;
uniqueKey: string;
}], Promise<Promise<RemoteEntryExports | undefined> | undefined>>;
afterLoadEntry: AsyncHook<[{
origin: ModuleFederation;
remoteInfo: RemoteInfo;
remoteEntryExports?: false | void | RemoteEntryExports | undefined;
error?: unknown;
recovered?: boolean;
}], void>;
beforeInitRemote: AsyncHook<[{
id?: string;
remoteInfo: RemoteInfo;
remoteSnapshot?: ModuleInfo;
origin: ModuleFederation;
}], void>;
afterInitRemote: AsyncHook<[{
id?: string;
remoteInfo: RemoteInfo;
remoteSnapshot?: ModuleInfo;
remoteEntryExports?: RemoteEntryExports;
error?: unknown;
cached?: boolean;
origin: ModuleFederation;
}], void>;
beforeGetExpose: AsyncHook<[{
id: string;
expose: string;
moduleInfo: RemoteInfo;
remoteEntryExports: RemoteEntryExports;
origin: ModuleFederation;
}], void>;
afterGetExpose: AsyncHook<[{
id: string;
expose: string;
moduleInfo: RemoteInfo;
remoteEntryExports: RemoteEntryExports;
moduleFactory?: RemoteModuleFactory;
error?: unknown;
origin: ModuleFederation;
}], void>;
beforeExecuteFactory: AsyncHook<[{
id: string;
expose: string;
moduleInfo: RemoteInfo;
loadFactory: boolean;
origin: ModuleFederation;
}], void>;
afterExecuteFactory: AsyncHook<[{
id: string;
expose: string;
moduleInfo: RemoteInfo;
loadFactory: boolean;
exposeModule?: unknown;
error?: unknown;
origin: ModuleFederation;
}], void>;
getModuleFactory: AsyncHook<[{
remoteEntryExports: RemoteEntryExports;
expose: string;
moduleInfo: RemoteInfo;
}], RemoteModuleFactory | Promise<RemoteModuleFactory | undefined> | undefined>;
}>;
bridgeHook: PluginSystem<{
beforeBridgeRender: SyncHook<[Record<string, any>], void | Record<string, any>>;
afterBridgeRender: SyncHook<[Record<string, any>], void | Record<string, any>>;
beforeBridgeDestroy: SyncHook<[Record<string, any>], void | Record<string, any>>;
afterBridgeDestroy: SyncHook<[Record<string, any>], void | Record<string, any>>;
}>;
moduleInfo?: GlobalModuleInfo[string];
constructor(userOptions: UserOptions);
initOptions(userOptions: UserOptions): Options;
loadShare<T>(pkgName: string, extraOptions?: {
customShareInfo?: Partial<Shared>;
resolver?: (sharedOptions: ShareInfos[string]) => Shared;
}): Promise<false | (() => T | undefined)>;
loadShareSync<T>(pkgName: string, extraOptions?: {
customShareInfo?: Partial<Shared>;
from?: 'build' | 'runtime';
resolver?: (sharedOptions: ShareInfos[string]) => Shared;
}): () => T | never;
initializeSharing(shareScopeName?: string, extraOptions?: {
initScope?: InitScope;
from?: CallFrom;
strategy?: Shared['strategy'];
}): Array<Promise<void>>;
initRawContainer(name: string, url: string, container: RemoteEntryExports): Module$1;
loadRemote<T>(id: string, options?: {
loadFactory?: boolean;
from: CallFrom;
}): Promise<T | null>;
preloadRemote(preloadOptions: Array<PreloadRemoteArgs>): Promise<void>;
initShareScopeMap(scopeName: string, shareScope: ShareScopeMap[string], extraOptions?: {
hostShareScopeMap?: ShareScopeMap;
}): void;
formatOptions(globalOptions: Options, userOptions: UserOptions): Options;
registerPlugins(plugins: UserOptions['plugins']): void;
registerRemotes(remotes: Remote[], options?: {
force?: boolean;
}): void;
registerShared(shared: UserOptions['shared']): void;
} //#endregion
//#endregion
//#region ../runtime-core/dist/module/index.d.ts
//#region src/module/index.d.ts
type ModuleOptions = ConstructorParameters<typeof Module$1>[0];
type RemoteModuleFactory = () => unknown | Promise<unknown>;
declare class Module$1 {
remoteInfo: RemoteInfo;
inited: boolean;
initing: boolean;
initPromise?: Promise<void>;
remoteEntryExports?: RemoteEntryExports;
lib: RemoteEntryExports | undefined;
host: ModuleFederation;
constructor({
remoteInfo,
host
}: {
remoteInfo: RemoteInfo;
host: ModuleFederation;
});
getEntry(expose?: string): Promise<RemoteEntryExports>;
init(id?: string, remoteSnapshot?: ModuleInfo, rawInitScope?: InitScope, expose?: string): Promise<RemoteEntryExports>;
get(id: string, expose: string, options?: {
loadFactory?: boolean;
}, remoteSnapshot?: ModuleInfo): Promise<unknown>;
private wraperFactory;
} //#endregion
//#endregion
//#region src/runtime-plugins/dynamic-remote-type-hints-plugin.d.ts
declare function dynamicRemoteTypeHintsPlugin(): ModuleFederationRuntimePlugin;
export = dynamicRemoteTypeHintsPlugin;

View File

@@ -0,0 +1,74 @@
const require_Action = require('./Action-CzhPMw2i.js');
const require_utils = require('./utils-7KqCZHbb.js');
let isomorphic_ws = require("isomorphic-ws");
isomorphic_ws = require_Action.__toESM(isomorphic_ws);
//#region src/server/message/Action/FetchTypes.ts
var FetchTypesAction = class extends require_Action.Action {
constructor(payload) {
super({ payload }, require_Action.ActionKind.FETCH_TYPES);
}
};
//#endregion
//#region src/server/message/Action/AddDynamicRemote.ts
var AddDynamicRemoteAction = class extends require_Action.Action {
constructor(payload) {
super({ payload }, require_Action.ActionKind.ADD_DYNAMIC_REMOTE);
}
};
//#endregion
//#region src/server/createWebsocket.ts
function createWebsocket() {
return new isomorphic_ws.default(`ws://127.0.0.1:${require_Action.DEFAULT_WEB_SOCKET_PORT}?WEB_SOCKET_CONNECT_MAGIC_ID=${require_Action.WEB_SOCKET_CONNECT_MAGIC_ID}`);
}
//#endregion
//#region src/runtime-plugins/dynamic-remote-type-hints-plugin.ts
const PLUGIN_NAME = "dynamic-remote-type-hints-plugin";
function dynamicRemoteTypeHintsPlugin() {
let ws = createWebsocket();
let isConnected = false;
ws.onopen = () => {
isConnected = true;
};
ws.onerror = (err) => {
console.error(`[ ${PLUGIN_NAME} ] err: ${err}`);
};
return {
name: "dynamic-remote-type-hints-plugin",
registerRemote(args) {
const { remote, origin } = args;
try {
if (!isConnected) return args;
if (!("entry" in remote)) return args;
const defaultIpV4 = typeof FEDERATION_IPV4 === "string" ? FEDERATION_IPV4 : "127.0.0.1";
const remoteIp = require_utils.getIpFromEntry(remote.entry, defaultIpV4);
const remoteInfo = {
name: remote.name,
url: remote.entry,
alias: remote.alias || remote.name
};
if (remoteIp) ws.send(JSON.stringify(new AddDynamicRemoteAction({
remoteIp,
remoteInfo,
name: origin.name,
ip: defaultIpV4
})));
ws.send(JSON.stringify(new FetchTypesAction({
name: origin.name,
ip: defaultIpV4,
remoteInfo
})));
return args;
} catch (err) {
console.error(new Error(err));
return args;
}
}
};
}
//#endregion
module.exports = dynamicRemoteTypeHintsPlugin;

View File

@@ -0,0 +1,47 @@
//#region src/server/message/Message.ts
var Message = class {
constructor(type, kind) {
this.type = type;
this.kind = kind;
this.time = Date.now();
}
};
//#endregion
//#region src/server/constant.ts
const DEFAULT_WEB_SOCKET_PORT = 16322;
const WEB_SOCKET_CONNECT_MAGIC_ID = "1hpzW-zo2z-o8io-gfmV1-2cb1d82";
const MF_SERVER_IDENTIFIER = "Module Federation DTS";
const WEB_CLIENT_OPTIONS_IDENTIFIER = "__WEB_CLIENT_OPTIONS__";
const DEFAULT_TAR_NAME = "@mf-types.zip";
let UpdateMode = /* @__PURE__ */ function(UpdateMode) {
UpdateMode["POSITIVE"] = "POSITIVE";
UpdateMode["PASSIVE"] = "PASSIVE";
return UpdateMode;
}({});
//#endregion
//#region src/server/message/Action/Action.ts
let ActionKind = /* @__PURE__ */ function(ActionKind) {
ActionKind["ADD_SUBSCRIBER"] = "ADD_SUBSCRIBER";
ActionKind["EXIT_SUBSCRIBER"] = "EXIT_SUBSCRIBER";
ActionKind["ADD_PUBLISHER"] = "ADD_PUBLISHER";
ActionKind["UPDATE_PUBLISHER"] = "UPDATE_PUBLISHER";
ActionKind["NOTIFY_SUBSCRIBER"] = "NOTIFY_SUBSCRIBER";
ActionKind["EXIT_PUBLISHER"] = "EXIT_PUBLISHER";
ActionKind["ADD_WEB_CLIENT"] = "ADD_WEB_CLIENT";
ActionKind["NOTIFY_WEB_CLIENT"] = "NOTIFY_WEB_CLIENT";
ActionKind["FETCH_TYPES"] = "FETCH_TYPES";
ActionKind["ADD_DYNAMIC_REMOTE"] = "ADD_DYNAMIC_REMOTE";
return ActionKind;
}({});
var Action = class extends Message {
constructor(content, kind) {
super("Action", kind);
const { payload } = content;
this.payload = payload;
}
};
//#endregion
export { MF_SERVER_IDENTIFIER as a, WEB_SOCKET_CONNECT_MAGIC_ID as c, DEFAULT_WEB_SOCKET_PORT as i, Message as l, ActionKind as n, UpdateMode as o, DEFAULT_TAR_NAME as r, WEB_CLIENT_OPTIONS_IDENTIFIER as s, Action as t };

View File

@@ -0,0 +1,718 @@
import { a as MF_SERVER_IDENTIFIER, c as WEB_SOCKET_CONNECT_MAGIC_ID, i as DEFAULT_WEB_SOCKET_PORT, l as Message, n as ActionKind, o as UpdateMode } from "./Action-DNNg2YDh.mjs";
import * as fs$1 from "fs";
import * as path$1 from "path";
import { SEPARATOR, createLogger } from "@module-federation/sdk";
import net from "net";
import os from "os";
import WebSocket from "isomorphic-ws";
import { createServer } from "http";
import schedule from "node-schedule";
import { parse } from "url";
//#region src/server/message/API/API.ts
let APIKind = /* @__PURE__ */ function(APIKind) {
APIKind["UPDATE_SUBSCRIBER"] = "UPDATE_SUBSCRIBER";
APIKind["RELOAD_WEB_CLIENT"] = "RELOAD_WEB_CLIENT";
APIKind["FETCH_TYPES"] = "FETCH_TYPES";
return APIKind;
}({});
var API = class extends Message {
constructor(content, kind) {
super("API", kind);
const { code, payload } = content;
this.code = code;
this.payload = payload;
}
};
//#endregion
//#region src/server/message/API/UpdateSubscriber.ts
var UpdateSubscriberAPI = class extends API {
constructor(payload) {
super({
code: 0,
payload
}, APIKind.UPDATE_SUBSCRIBER);
}
};
//#endregion
//#region src/server/message/API/ReloadWebClient.ts
var ReloadWebClientAPI = class extends API {
constructor(payload) {
super({
code: 0,
payload
}, APIKind.RELOAD_WEB_CLIENT);
}
};
//#endregion
//#region src/server/message/API/FetchTypes.ts
var FetchTypesAPI = class extends API {
constructor(payload) {
super({
code: 0,
payload
}, APIKind.FETCH_TYPES);
}
};
//#endregion
//#region src/server/message/Log/Log.ts
let LogLevel = /* @__PURE__ */ function(LogLevel) {
LogLevel["LOG"] = "LOG";
LogLevel["WARN"] = "WARN";
LogLevel["ERROR"] = "ERROR";
return LogLevel;
}({});
let LogKind = /* @__PURE__ */ function(LogKind) {
LogKind["BrokerExitLog"] = "BrokerExitLog";
LogKind["PublisherRegisteredLog"] = "PublisherRegisteredLog";
return LogKind;
}({});
var Log = class extends Message {
constructor(level, kind, ignoreVerbose = false) {
super("Log", kind);
this.ignoreVerbose = false;
this.level = level;
this.ignoreVerbose = ignoreVerbose;
}
};
//#endregion
//#region src/server/message/Log/BrokerExitLog.ts
var BrokerExitLog = class extends Log {
constructor() {
super(LogLevel.LOG, LogKind.BrokerExitLog);
}
};
//#endregion
//#region src/server/utils/log.ts
const logger$1 = createLogger(`[ ${MF_SERVER_IDENTIFIER} ]`);
function fileLog(msg, module, level) {
if (!process?.env?.["FEDERATION_DEBUG"]) return;
try {
const logDir = ".mf";
const logFile = path$1.join(logDir, "typesGenerate.log");
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
if (!fs$1.existsSync(logDir)) fs$1.mkdirSync(logDir, { recursive: true });
fs$1.appendFileSync(logFile, `[${timestamp}] [${level.toUpperCase()}] ${module} - ${msg}\n`);
} catch {}
}
function error(error, action, from) {
const err = error instanceof Error ? error : /* @__PURE__ */ new Error(`${action} error`);
fileLog(`[${action}] error: ${err}`, from, "fatal");
return err.toString();
}
//#endregion
//#region src/server/utils/getIPV4.ts
const localIpv4 = "127.0.0.1";
const getIpv4Interfaces = () => {
try {
const interfaces = os.networkInterfaces();
const ipv4Interfaces = [];
Object.values(interfaces).forEach((detail) => {
detail?.forEach((detail) => {
const familyV4Value = typeof detail.family === "string" ? "IPv4" : 4;
if (detail.family === familyV4Value && detail.address !== localIpv4) ipv4Interfaces.push(detail);
});
});
return ipv4Interfaces;
} catch (_err) {
return [];
}
};
const getIPV4 = () => {
return (getIpv4Interfaces()[0] || { address: localIpv4 }).address;
};
//#endregion
//#region src/server/utils/index.ts
function getIdentifier(options) {
const { ip, name } = options;
return `mf ${SEPARATOR}${name}${ip ? `${SEPARATOR}${ip}` : ""}`;
}
function fib(n) {
let i = 2;
const res = [
0,
1,
1
];
while (i <= n) {
res[i] = res[i - 1] + res[i - 2];
i++;
}
return res[n];
}
function getFreePort() {
return new Promise((resolve, reject) => {
const server = net.createServer();
server.unref();
server.on("error", reject);
server.listen(0, () => {
const { port } = server.address();
server.close(() => {
resolve(port);
});
});
});
}
//#endregion
//#region src/server/Publisher.ts
var Publisher = class {
constructor(ctx) {
this._name = ctx.name;
this._ip = ctx.ip;
this._remoteTypeTarPath = ctx.remoteTypeTarPath;
this._subscribers = /* @__PURE__ */ new Map();
this._ws = ctx.ws;
this.dynamicRemoteMap = /* @__PURE__ */ new Map();
}
get identifier() {
return getIdentifier({
name: this._name,
ip: this._ip
});
}
get name() {
return this._name;
}
get ip() {
return this._ip;
}
get remoteTypeTarPath() {
return this._remoteTypeTarPath;
}
get hasSubscribes() {
return Boolean(this._subscribers.size);
}
get subscribers() {
return this._subscribers;
}
addSubscriber(identifier, subscriber) {
fileLog(`${this.name} set subscriber: ${identifier}`, "Publisher", "info");
this._subscribers.set(identifier, subscriber);
}
removeSubscriber(identifier) {
if (this._subscribers.has(identifier)) {
fileLog(`${this.name} removeSubscriber: ${identifier}`, "Publisher", "warn");
this._subscribers.delete(identifier);
}
}
notifySubscriber(subscriberIdentifier, options) {
const subscriber = this._subscribers.get(subscriberIdentifier);
if (!subscriber) {
fileLog(`[notifySubscriber] ${this.name} notifySubscriber: ${subscriberIdentifier}, does not exits`, "Publisher", "error");
return;
}
const api = new UpdateSubscriberAPI(options);
subscriber.send(JSON.stringify(api));
fileLog(`[notifySubscriber] ${this.name} notifySubscriber: ${JSON.stringify(subscriberIdentifier)}, message: ${JSON.stringify(api)}`, "Publisher", "info");
}
fetchRemoteTypes(options) {
fileLog(`[fetchRemoteTypes] ${this.name} fetchRemoteTypes, options: ${JSON.stringify(options)}, ws: ${Boolean(this._ws)}`, "Publisher", "info");
if (!this._ws) return;
const api = new FetchTypesAPI(options);
this._ws.send(JSON.stringify(api));
}
notifySubscribers(options) {
const api = new UpdateSubscriberAPI(options);
this.broadcast(api);
}
broadcast(message) {
if (this.hasSubscribes) this._subscribers.forEach((subscriber, key) => {
fileLog(`[BroadCast] ${this.name} notifySubscriber: ${key}, PID: ${process.pid}, message: ${JSON.stringify(message)}`, "Publisher", "info");
subscriber.send(JSON.stringify(message));
});
else fileLog(`[BroadCast] ${this.name}'s subscribe is empty`, "Publisher", "warn");
}
close() {
this._ws = void 0;
this._subscribers.forEach((_subscriber, identifier) => {
fileLog(`[BroadCast] close ${this.name} remove: ${identifier}`, "Publisher", "warn");
this.removeSubscriber(identifier);
});
}
};
//#endregion
//#region src/server/message/Action/Update.ts
let UpdateKind = /* @__PURE__ */ function(UpdateKind) {
UpdateKind["UPDATE_TYPE"] = "UPDATE_TYPE";
UpdateKind["RELOAD_PAGE"] = "RELOAD_PAGE";
return UpdateKind;
}({});
//#endregion
//#region src/server/broker/Broker.ts
var Broker = class Broker {
static {
this.WEB_SOCKET_CONNECT_MAGIC_ID = WEB_SOCKET_CONNECT_MAGIC_ID;
}
static {
this.DEFAULT_WEB_SOCKET_PORT = DEFAULT_WEB_SOCKET_PORT;
}
static {
this.DEFAULT_SECURE_WEB_SOCKET_PORT = 16324;
}
static {
this.DEFAULT_WAITING_TIME = 1.5 * 60 * 60 * 1e3;
}
constructor() {
this._publisherMap = /* @__PURE__ */ new Map();
this._webClientMap = /* @__PURE__ */ new Map();
this._tmpSubscriberShelter = /* @__PURE__ */ new Map();
this._scheduleJob = null;
this._setSchedule();
this._startWsServer();
this._stopWhenSIGTERMOrSIGINT();
this._handleUnexpectedExit();
}
get hasPublishers() {
return Boolean(this._publisherMap.size);
}
async _startWsServer() {
const wsHandler = (ws, req) => {
const { url: reqUrl = "" } = req;
const { query } = parse(reqUrl, true);
const { WEB_SOCKET_CONNECT_MAGIC_ID } = query;
if (WEB_SOCKET_CONNECT_MAGIC_ID === Broker.WEB_SOCKET_CONNECT_MAGIC_ID) {
ws.on("message", (message) => {
try {
const text = message.toString();
const action = JSON.parse(text);
fileLog(`${action?.kind} action received `, "Broker", "info");
this._takeAction(action, ws);
} catch (error) {
fileLog(`parse action message error: ${error}`, "Broker", "error");
}
});
ws.on("error", (e) => {
fileLog(`parse action message error: ${e}`, "Broker", "error");
});
} else {
ws.send("Invalid CONNECT ID.");
fileLog("Invalid CONNECT ID.", "Broker", "warn");
ws.close();
}
};
const server = createServer();
this._webSocketServer = new WebSocket.Server({ noServer: true });
this._webSocketServer.on("error", (err) => {
fileLog(`ws error: \n${err.message}\n ${err.stack}`, "Broker", "error");
});
this._webSocketServer.on("listening", () => {
fileLog(`WebSocket server is listening on port ${Broker.DEFAULT_WEB_SOCKET_PORT}`, "Broker", "info");
});
this._webSocketServer.on("connection", wsHandler);
this._webSocketServer.on("close", (code) => {
fileLog(`WebSocket Server Close with Code ${code}`, "Broker", "warn");
this._webSocketServer && this._webSocketServer.close();
this._webSocketServer = void 0;
});
server.on("upgrade", (req, socket, head) => {
if (req.url) {
const { pathname } = parse(req.url);
if (pathname === "/") this._webSocketServer?.handleUpgrade(req, socket, head, (ws) => {
this._webSocketServer?.emit("connection", ws, req);
});
}
});
server.listen(Broker.DEFAULT_WEB_SOCKET_PORT);
}
async _takeAction(action, client) {
const { kind, payload } = action;
if (kind === ActionKind.ADD_PUBLISHER) await this._addPublisher(payload, client);
if (kind === ActionKind.UPDATE_PUBLISHER) await this._updatePublisher(payload, client);
if (kind === ActionKind.ADD_SUBSCRIBER) await this._addSubscriber(payload, client);
if (kind === ActionKind.EXIT_SUBSCRIBER) await this._removeSubscriber(payload, client);
if (kind === ActionKind.EXIT_PUBLISHER) await this._removePublisher(payload, client);
if (kind === ActionKind.ADD_WEB_CLIENT) await this._addWebClient(payload, client);
if (kind === ActionKind.NOTIFY_WEB_CLIENT) await this._notifyWebClient(payload, client);
if (kind === ActionKind.FETCH_TYPES) await this._fetchTypes(payload, client);
if (kind === ActionKind.ADD_DYNAMIC_REMOTE) this._addDynamicRemote(payload);
}
async _addPublisher(context, client) {
const { name, ip, remoteTypeTarPath } = context ?? {};
const identifier = getIdentifier({
name,
ip
});
if (this._publisherMap.has(identifier)) {
fileLog(`[${ActionKind.ADD_PUBLISHER}] ${identifier} has been added, this action will be ignored`, "Broker", "warn");
return;
}
try {
const publisher = new Publisher({
name,
ip,
remoteTypeTarPath,
ws: client
});
this._publisherMap.set(identifier, publisher);
fileLog(`[${ActionKind.ADD_PUBLISHER}] ${identifier} Adding Publisher Succeed`, "Broker", "info");
const tmpSubScribers = this._getTmpSubScribers(identifier);
if (tmpSubScribers) {
fileLog(`[${ActionKind.ADD_PUBLISHER}] consumeTmpSubscriber set ${publisher.name}s subscribers `, "Broker", "info");
this._consumeTmpSubScribers(publisher, tmpSubScribers);
this._clearTmpSubScriberRelation(identifier);
}
} catch (err) {
const msg = error(err, ActionKind.ADD_PUBLISHER, "Broker");
client.send(msg);
client.close();
}
}
async _updatePublisher(context, client) {
const { name, updateMode, updateKind, updateSourcePaths, remoteTypeTarPath, ip } = context ?? {};
const identifier = getIdentifier({
name,
ip
});
if (!this._publisherMap.has(identifier)) {
fileLog(`[${ActionKind.UPDATE_PUBLISHER}] ${identifier} has not been started, this action will be ignored
this._publisherMap: ${JSON.stringify(this._publisherMap.entries())}
`, "Broker", "warn");
return;
}
try {
const publisher = this._publisherMap.get(identifier);
fileLog(`[${ActionKind.UPDATE_PUBLISHER}] ${identifier} update, and notify subscribers to update`, "Broker", "info");
if (publisher) {
publisher.notifySubscribers({
remoteTypeTarPath,
name,
updateMode,
updateKind,
updateSourcePaths: updateSourcePaths || []
});
this._publisherMap.forEach((p) => {
if (p.name === publisher.name) return;
const dynamicRemoteInfo = p.dynamicRemoteMap.get(identifier);
if (dynamicRemoteInfo) {
fileLog(`dynamicRemoteInfo: ${JSON.stringify(dynamicRemoteInfo)}, identifier:${identifier} publish: ${p.name}`, "Broker", "info");
p.fetchRemoteTypes({
remoteInfo: dynamicRemoteInfo,
once: false
});
}
});
}
} catch (err) {
const msg = error(err, ActionKind.UPDATE_PUBLISHER, "Broker");
client.send(msg);
client.close();
}
}
async _fetchTypes(context, _client) {
const { name, ip, remoteInfo } = context ?? {};
const identifier = getIdentifier({
name,
ip
});
try {
const publisher = this._publisherMap.get(identifier);
fileLog(`[${ActionKind.FETCH_TYPES}] ${identifier} fetch types`, "Broker", "info");
if (publisher) publisher.fetchRemoteTypes({
remoteInfo,
once: true
});
} catch (err) {
fileLog(`[${ActionKind.FETCH_TYPES}] ${identifier} fetch types fail , error info: ${err}`, "Broker", "error");
}
}
_addDynamicRemote(context) {
const { name, ip, remoteInfo, remoteIp } = context ?? {};
const identifier = getIdentifier({
name,
ip
});
const publisher = this._publisherMap.get(identifier);
const remoteId = getIdentifier({
name: remoteInfo.name,
ip: remoteIp
});
fileLog(`[${ActionKind.ADD_DYNAMIC_REMOTE}] identifier:${identifier},publisher: ${publisher.name}, remoteId:${remoteId}`, "Broker", "error");
if (!publisher || publisher.dynamicRemoteMap.has(remoteId)) return;
publisher.dynamicRemoteMap.set(remoteId, remoteInfo);
}
async _addSubscriber(context, client) {
const { publishers, name: subscriberName } = context ?? {};
publishers.forEach((publisher) => {
const { name, ip } = publisher;
const identifier = getIdentifier({
name,
ip
});
if (!this._publisherMap.has(identifier)) {
fileLog(`[${ActionKind.ADD_SUBSCRIBER}]: ${identifier} has not been started, ${subscriberName} will add the relation to tmp shelter`, "Broker", "warn");
this._addTmpSubScriberRelation({
name: getIdentifier({
name: context.name,
ip: context.ip
}),
client
}, publisher);
return;
}
try {
const registeredPublisher = this._publisherMap.get(identifier);
if (registeredPublisher) {
registeredPublisher.addSubscriber(getIdentifier({
name: subscriberName,
ip: context.ip
}), client);
fileLog(`[${ActionKind.ADD_SUBSCRIBER}]: ${identifier} has been started, Adding Subscriber ${subscriberName} Succeed, this.__publisherMap are: ${JSON.stringify(Array.from(this._publisherMap.entries()))}`, "Broker", "info");
registeredPublisher.notifySubscriber(getIdentifier({
name: subscriberName,
ip: context.ip
}), {
updateKind: UpdateKind.UPDATE_TYPE,
updateMode: UpdateMode.PASSIVE,
updateSourcePaths: [registeredPublisher.name],
remoteTypeTarPath: registeredPublisher.remoteTypeTarPath,
name: registeredPublisher.name
});
fileLog(`[${ActionKind.ADD_SUBSCRIBER}]: notifySubscriber Subscriber ${subscriberName}, updateMode: "PASSIVE", updateSourcePaths: ${registeredPublisher.name}`, "Broker", "info");
}
} catch (err) {
const msg = error(err, ActionKind.ADD_SUBSCRIBER, "Broker");
client.send(msg);
client.close();
}
});
}
async _removeSubscriber(context, client) {
const { publishers } = context ?? {};
const subscriberIdentifier = getIdentifier({
name: context?.name,
ip: context?.ip
});
publishers.forEach((publisher) => {
const { name, ip } = publisher;
const identifier = getIdentifier({
name,
ip
});
const registeredPublisher = this._publisherMap.get(identifier);
if (!registeredPublisher) {
fileLog(`[${ActionKind.EXIT_SUBSCRIBER}], ${identifier} does not exit `, "Broker", "warn");
return;
}
try {
fileLog(`[${ActionKind.EXIT_SUBSCRIBER}], ${identifier} will exit `, "Broker", "INFO");
registeredPublisher.removeSubscriber(subscriberIdentifier);
this._clearTmpSubScriberRelation(identifier);
if (!registeredPublisher.hasSubscribes) this._publisherMap.delete(identifier);
if (!this.hasPublishers) this.exit();
} catch (err) {
const msg = error(err, ActionKind.EXIT_SUBSCRIBER, "Broker");
client.send(msg);
client.close();
}
});
}
async _removePublisher(context, client) {
const { name, ip } = context ?? {};
const identifier = getIdentifier({
name,
ip
});
const publisher = this._publisherMap.get(identifier);
if (!publisher) {
fileLog(`[${ActionKind.EXIT_PUBLISHER}]: ${identifier}} has not been added, this action will be ingored`, "Broker", "warn");
return;
}
try {
const { subscribers } = publisher;
subscribers.forEach((subscriber, subscriberIdentifier) => {
this._addTmpSubScriberRelation({
name: subscriberIdentifier,
client: subscriber
}, {
name: publisher.name,
ip: publisher.ip
});
fileLog(`[${ActionKind.EXIT_PUBLISHER}]: ${identifier} is removing , subscriber: ${subscriberIdentifier} will be add tmpSubScriberRelation`, "Broker", "info");
});
this._publisherMap.delete(identifier);
fileLog(`[${ActionKind.EXIT_PUBLISHER}]: ${identifier} is removed `, "Broker", "info");
if (!this.hasPublishers) {
fileLog(`[${ActionKind.EXIT_PUBLISHER}]: _publisherMap is empty, all server will exit `, "Broker", "warn");
this.exit();
}
} catch (err) {
const msg = error(err, ActionKind.EXIT_PUBLISHER, "Broker");
client.send(msg);
client.close();
}
}
async _addWebClient(context, client) {
const { name } = context ?? {};
const identifier = getIdentifier({ name });
if (this._webClientMap.has(identifier)) fileLog(`${identifier}} has been added, this action will override prev WebClient`, "Broker", "warn");
try {
this._webClientMap.set(identifier, client);
fileLog(`${identifier} adding WebClient Succeed`, "Broker", "info");
} catch (err) {
const msg = error(err, ActionKind.ADD_WEB_CLIENT, "Broker");
client.send(msg);
client.close();
}
}
async _notifyWebClient(context, client) {
const { name, updateMode } = context ?? {};
const identifier = getIdentifier({ name });
const webClient = this._webClientMap.get(identifier);
if (!webClient) {
fileLog(`[${ActionKind.NOTIFY_WEB_CLIENT}] ${identifier} has not been added, this action will be ignored`, "Broker", "warn");
return;
}
try {
const api = new ReloadWebClientAPI({
name,
updateMode
});
webClient.send(JSON.stringify(api));
fileLog(`[${ActionKind.NOTIFY_WEB_CLIENT}] Notify ${name} WebClient Succeed`, "Broker", "info");
} catch (err) {
const msg = error(err, ActionKind.NOTIFY_WEB_CLIENT, "Broker");
client.send(msg);
client.close();
}
}
_addTmpSubScriberRelation(subscriber, publisher) {
const publisherIdentifier = getIdentifier({
name: publisher.name,
ip: publisher.ip
});
const subscriberIdentifier = subscriber.name;
const shelter = this._tmpSubscriberShelter.get(publisherIdentifier);
if (!shelter) {
const map = /* @__PURE__ */ new Map();
map.set(subscriberIdentifier, subscriber);
this._tmpSubscriberShelter.set(publisherIdentifier, {
subscribers: map,
timestamp: Date.now()
});
fileLog(`[AddTmpSubscriberRelation] ${publisherIdentifier}'s subscriber has ${subscriberIdentifier} `, "Broker", "info");
return;
}
if (shelter.subscribers.get(subscriberIdentifier)) {
fileLog(`[AddTmpSubscriberRelation] ${publisherIdentifier} and ${subscriberIdentifier} relation has been added`, "Broker", "warn");
shelter.subscribers.set(subscriberIdentifier, subscriber);
shelter.timestamp = Date.now();
} else {
fileLog(`AddTmpSubscriberLog ${publisherIdentifier}'s shelter has been added, update shelter.subscribers ${subscriberIdentifier}`, "Broker", "warn");
shelter.subscribers.set(subscriberIdentifier, subscriber);
}
}
_getTmpSubScribers(publisherIdentifier) {
return this._tmpSubscriberShelter.get(publisherIdentifier)?.subscribers;
}
_consumeTmpSubScribers(publisher, tmpSubScribers) {
tmpSubScribers.forEach((tmpSubScriber, identifier) => {
fileLog(`notifyTmpSubScribers ${publisher.name} will be add a subscriber: ${identifier} `, "Broker", "warn");
publisher.addSubscriber(identifier, tmpSubScriber.client);
publisher.notifySubscriber(identifier, {
updateKind: UpdateKind.UPDATE_TYPE,
updateMode: UpdateMode.PASSIVE,
updateSourcePaths: [publisher.name],
remoteTypeTarPath: publisher.remoteTypeTarPath,
name: publisher.name
});
});
}
_clearTmpSubScriberRelation(identifier) {
this._tmpSubscriberShelter.delete(identifier);
}
_clearTmpSubScriberRelations() {
this._tmpSubscriberShelter.clear();
}
_disconnect() {
this._publisherMap.forEach((publisher) => {
publisher.close();
});
}
_setSchedule() {
const rule = new schedule.RecurrenceRule();
if (Number(process.env["FEDERATION_SERVER_TEST"])) {
const interval = Number(process.env["FEDERATION_SERVER_TEST"]) / 1e3;
const second = [];
for (let i = 0; i < 60; i = i + interval) second.push(i);
rule.second = second;
} else {
rule.second = 0;
rule.hour = [
0,
3,
6,
9,
12,
15,
18
];
rule.minute = 0;
}
const serverTest = Number(process.env["FEDERATION_SERVER_TEST"]);
this._scheduleJob = schedule.scheduleJob(rule, () => {
this._tmpSubscriberShelter.forEach((tmpSubscriber, identifier) => {
fileLog(` _clearTmpSubScriberRelation ${identifier}, ${Date.now() - tmpSubscriber.timestamp >= (process.env["GARFISH_MODULE_SERVER_TEST"] ? serverTest : Broker.DEFAULT_WAITING_TIME)}`, "Broker", "info");
if (Date.now() - tmpSubscriber.timestamp >= (process.env["FEDERATION_SERVER_TEST"] ? serverTest : Broker.DEFAULT_WAITING_TIME)) this._clearTmpSubScriberRelation(identifier);
});
});
}
_clearSchedule() {
if (!this._scheduleJob) return;
this._scheduleJob.cancel();
this._scheduleJob = null;
}
_stopWhenSIGTERMOrSIGINT() {
process.on("SIGTERM", () => {
this.exit();
});
process.on("SIGINT", () => {
this.exit();
});
}
_handleUnexpectedExit() {
process.on("unhandledRejection", (error) => {
console.error("Unhandled Rejection Error: ", error);
fileLog(`Unhandled Rejection Error: ${error}`, "Broker", "fatal");
process.exit(1);
});
process.on("uncaughtException", (error) => {
console.error("Unhandled Exception Error: ", error);
fileLog(`Unhandled Rejection Error: ${error}`, "Broker", "fatal");
process.exit(1);
});
}
async start() {}
exit() {
const brokerExitLog = new BrokerExitLog();
this.broadcast(JSON.stringify(brokerExitLog));
this._disconnect();
this._clearSchedule();
this._clearTmpSubScriberRelations();
this._webSocketServer && this._webSocketServer.close();
this._secureWebSocketServer && this._secureWebSocketServer.close();
process.exit(0);
}
broadcast(message) {
fileLog(`[broadcast] exit info : ${JSON.stringify(message)}`, "Broker", "warn");
this._webSocketServer?.clients.forEach((client) => {
client.send(JSON.stringify(message));
});
this._secureWebSocketServer?.clients.forEach((client) => {
client.send(JSON.stringify(message));
});
}
};
//#endregion
export { getIdentifier as a, logger$1 as c, getFreePort as i, LogKind as l, UpdateKind as n, getIPV4 as o, fib as r, fileLog as s, Broker as t, APIKind as u };

View File

@@ -0,0 +1,208 @@
import { a as cloneDeepOptions, n as RpcGMCallTypes, o as getDTSManagerConstructor, s as isDebugMode, t as exposeRpc, x as __exportAll } from "./expose-rpc-BgxOTFXQ.mjs";
import path from "path";
import { randomUUID } from "crypto";
import * as child_process from "child_process";
import { fileURLToPath } from "url";
import * as process$2 from "process";
//#region src/core/rpc/rpc-error.ts
var RpcExitError = class extends Error {
constructor(message, code, signal) {
super(message);
this.code = code;
this.signal = signal;
this.name = "RpcExitError";
}
};
//#endregion
//#region src/core/rpc/wrap-rpc.ts
function createControlledPromise() {
let resolve = () => void 0;
let reject = () => void 0;
return {
promise: new Promise((aResolve, aReject) => {
resolve = aResolve;
reject = aReject;
}),
resolve,
reject
};
}
function wrapRpc(childProcess, options) {
return (async (...args) => {
if (!childProcess.send) throw new Error(`Process ${childProcess.pid} doesn't have IPC channels`);
else if (!childProcess.connected) throw new Error(`Process ${childProcess.pid} doesn't have open IPC channels`);
const { id, once } = options;
const { promise: resultPromise, resolve: resolveResult, reject: rejectResult } = createControlledPromise();
const { promise: sendPromise, resolve: resolveSend, reject: rejectSend } = createControlledPromise();
const handleMessage = (message) => {
if (message?.id === id) {
if (message.type === RpcGMCallTypes.RESOLVE) resolveResult(message.value);
else if (message.type === RpcGMCallTypes.REJECT) rejectResult(message.error);
}
if (once && childProcess?.kill) childProcess.kill("SIGTERM");
};
const handleClose = (code, signal) => {
rejectResult(new RpcExitError(code ? `Process ${childProcess.pid} exited with code ${code}${signal ? ` [${signal}]` : ""}` : `Process ${childProcess.pid} exited${signal ? ` [${signal}]` : ""}`, code, signal));
removeHandlers();
};
const removeHandlers = () => {
childProcess.off("message", handleMessage);
childProcess.off("close", handleClose);
};
if (once) childProcess.once("message", handleMessage);
else childProcess.on("message", handleMessage);
childProcess.on("close", handleClose);
childProcess.send({
type: RpcGMCallTypes.CALL,
id,
args
}, (error) => {
if (error) {
rejectSend(error);
removeHandlers();
} else resolveSend(void 0);
});
return sendPromise.then(() => resultPromise);
});
}
//#endregion
//#region src/core/rpc/rpc-worker.ts
const FEDERATION_WORKER_DATA_ENV_KEY = "VMOK_WORKER_DATA_ENV";
function createRpcWorker(modulePath, data, memoryLimit, once) {
const options = {
env: {
...process$2.env,
[FEDERATION_WORKER_DATA_ENV_KEY]: JSON.stringify(data || {})
},
stdio: [
"inherit",
"inherit",
"inherit",
"ipc"
],
serialization: "advanced"
};
if (memoryLimit) options.execArgv = [`--max-old-space-size=${memoryLimit}`];
let childProcess, remoteMethod;
const id = randomUUID();
return {
connect(...args) {
if (childProcess && !childProcess.connected) {
childProcess.send({
type: RpcGMCallTypes.EXIT,
id
});
childProcess = void 0;
remoteMethod = void 0;
}
if (!childProcess?.connected) {
childProcess = child_process.fork(modulePath, options);
remoteMethod = wrapRpc(childProcess, {
id,
once
});
}
if (!remoteMethod) return Promise.reject(/* @__PURE__ */ new Error("Worker is not connected - cannot perform RPC."));
return remoteMethod(...args);
},
terminate() {
try {
if (childProcess.connected) childProcess.send({
type: RpcGMCallTypes.EXIT,
id
}, (err) => {
if (err) console.error("Error sending message:", err);
});
} catch (error) {
if (error.code === "EPIPE") console.error("Pipe closed before message could be sent:", error);
else console.error("Unexpected error:", error);
}
childProcess = void 0;
remoteMethod = void 0;
},
get connected() {
return Boolean(childProcess?.connected);
},
get process() {
return childProcess;
},
get id() {
return id;
}
};
}
function getRpcWorkerData() {
return JSON.parse(process$2.env[FEDERATION_WORKER_DATA_ENV_KEY] || "{}");
}
//#endregion
//#region src/core/rpc/index.ts
var rpc_exports = /* @__PURE__ */ __exportAll({
RpcExitError: () => RpcExitError,
RpcGMCallTypes: () => RpcGMCallTypes,
createRpcWorker: () => createRpcWorker,
exposeRpc: () => exposeRpc,
getRpcWorkerData: () => getRpcWorkerData,
wrapRpc: () => wrapRpc
});
//#endregion
//#region src/core/lib/DtsWorker.ts
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const __extname = path.extname(__filename);
var DtsWorker = class {
constructor(options) {
this._options = cloneDeepOptions(options);
this.removeUnSerializationOptions();
this.rpcWorker = createRpcWorker(path.resolve(__dirname, `./fork-generate-dts${__extname}`), {}, void 0, true);
this._res = this.rpcWorker.connect(this._options);
}
removeUnSerializationOptions() {
if (this._options.remote?.moduleFederationConfig?.manifest) delete this._options.remote?.moduleFederationConfig?.manifest;
if (this._options.host?.moduleFederationConfig?.manifest) delete this._options.host?.moduleFederationConfig?.manifest;
}
get controlledPromise() {
const ensureChildProcessExit = () => {
try {
const pid = this.rpcWorker.process?.pid;
const rootPid = process.pid;
if (pid && rootPid !== pid) process.kill(pid, 0);
} catch (error) {
if (isDebugMode()) console.error(error);
}
};
return Promise.resolve(this._res).then(() => {
this.exit();
ensureChildProcessExit();
}).catch((err) => {
if (isDebugMode()) console.error(err);
ensureChildProcessExit();
});
}
exit() {
try {
this.rpcWorker?.terminate();
} catch (err) {
if (isDebugMode()) console.error(err);
}
}
};
//#endregion
//#region src/core/lib/generateTypesInChildProcess.ts
async function generateTypesInChildProcess(options) {
return new DtsWorker(options).controlledPromise;
}
//#endregion
//#region src/core/lib/consumeTypes.ts
async function consumeTypes(options) {
await new (getDTSManagerConstructor(options.host?.implementation))(options).consumeTypes();
}
//#endregion
export { createRpcWorker as a, rpc_exports as i, generateTypesInChildProcess as n, DtsWorker as r, consumeTypes as t };

View File

@@ -0,0 +1,5 @@
import { _ as retrieveMfTypesPath, c as isTSProject, d as DTSManager, f as HOST_API_TYPES_FILE_NAME, g as retrieveTypesZipPath, h as retrieveHostConfig, i as retrieveRemoteConfig, l as retrieveTypesAssetsInfo, m as REMOTE_API_TYPES_FILE_NAME, o as getDTSManagerConstructor, p as REMOTE_ALIAS_IDENTIFIER, r as generateTypes, u as validateOptions, v as retrieveOriginalOutDir } from "./expose-rpc-BgxOTFXQ.mjs";
import "./Broker-z82OgzMe.mjs";
import { i as rpc_exports, n as generateTypesInChildProcess, r as DtsWorker, t as consumeTypes } from "./consumeTypes-DCGF9bG3.mjs";
export { DTSManager, DtsWorker, HOST_API_TYPES_FILE_NAME, REMOTE_ALIAS_IDENTIFIER, REMOTE_API_TYPES_FILE_NAME, consumeTypes, generateTypes, generateTypesInChildProcess, getDTSManagerConstructor, isTSProject, retrieveHostConfig, retrieveMfTypesPath, retrieveOriginalOutDir, retrieveRemoteConfig, retrieveTypesAssetsInfo, retrieveTypesZipPath, rpc_exports as rpc, validateOptions };

View File

@@ -0,0 +1,73 @@
import { c as WEB_SOCKET_CONNECT_MAGIC_ID, i as DEFAULT_WEB_SOCKET_PORT, n as ActionKind, t as Action } from "./Action-DNNg2YDh.mjs";
import { t as getIpFromEntry } from "./utils-CkPvDGOy.mjs";
import WebSocket from "isomorphic-ws";
//#region src/server/message/Action/FetchTypes.ts
var FetchTypesAction = class extends Action {
constructor(payload) {
super({ payload }, ActionKind.FETCH_TYPES);
}
};
//#endregion
//#region src/server/message/Action/AddDynamicRemote.ts
var AddDynamicRemoteAction = class extends Action {
constructor(payload) {
super({ payload }, ActionKind.ADD_DYNAMIC_REMOTE);
}
};
//#endregion
//#region src/server/createWebsocket.ts
function createWebsocket() {
return new WebSocket(`ws://127.0.0.1:${DEFAULT_WEB_SOCKET_PORT}?WEB_SOCKET_CONNECT_MAGIC_ID=${WEB_SOCKET_CONNECT_MAGIC_ID}`);
}
//#endregion
//#region src/runtime-plugins/dynamic-remote-type-hints-plugin.ts
const PLUGIN_NAME = "dynamic-remote-type-hints-plugin";
function dynamicRemoteTypeHintsPlugin() {
let ws = createWebsocket();
let isConnected = false;
ws.onopen = () => {
isConnected = true;
};
ws.onerror = (err) => {
console.error(`[ ${PLUGIN_NAME} ] err: ${err}`);
};
return {
name: "dynamic-remote-type-hints-plugin",
registerRemote(args) {
const { remote, origin } = args;
try {
if (!isConnected) return args;
if (!("entry" in remote)) return args;
const defaultIpV4 = typeof FEDERATION_IPV4 === "string" ? FEDERATION_IPV4 : "127.0.0.1";
const remoteIp = getIpFromEntry(remote.entry, defaultIpV4);
const remoteInfo = {
name: remote.name,
url: remote.entry,
alias: remote.alias || remote.name
};
if (remoteIp) ws.send(JSON.stringify(new AddDynamicRemoteAction({
remoteIp,
remoteInfo,
name: origin.name,
ip: defaultIpV4
})));
ws.send(JSON.stringify(new FetchTypesAction({
name: origin.name,
ip: defaultIpV4,
remoteInfo
})));
return args;
} catch (err) {
console.error(new Error(err));
return args;
}
}
};
}
//#endregion
export { dynamicRemoteTypeHintsPlugin as default };

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
import { _ as retrieveMfTypesPath, b as ModuleFederationDevServer, g as retrieveTypesZipPath, h as retrieveHostConfig, i as retrieveRemoteConfig, n as RpcGMCallTypes, o as getDTSManagerConstructor, t as exposeRpc, y as createHttpServer } from "./expose-rpc-BgxOTFXQ.mjs";
import { o as UpdateMode, r as DEFAULT_TAR_NAME } from "./Action-DNNg2YDh.mjs";
import { n as UpdateKind, o as getIPV4, s as fileLog } from "./Broker-z82OgzMe.mjs";
import "./consumeTypes-DCGF9bG3.mjs";
import "./core.mjs";
import { t as getIpFromEntry } from "./utils-CkPvDGOy.mjs";
import { decodeName } from "@module-federation/sdk";
//#region src/dev-worker/handleWorkerMessage.ts
function handleDevWorkerMessage(message, options = {}) {
const { moduleServer, processExit = process.exit, pid = process.pid, log = () => void 0 } = options;
log(`ChildProcess(${pid}), message: ${JSON.stringify(message)} `, "forkDevWorker", "info");
if (message.type === RpcGMCallTypes.EXIT) {
log(`ChildProcess(${pid}) SIGTERM, Federation DevServer will exit...`, "forkDevWorker", "error");
moduleServer?.exit();
processExit(0);
}
}
//#endregion
//#region src/dev-worker/forkDevWorker.ts
let typesManager, serverAddress, moduleServer, cacheOptions;
function getLocalRemoteNames(options, encodeNameIdentifier) {
if (!options) return [];
let hostConfig;
try {
hostConfig = retrieveHostConfig(options);
} catch (e) {
fileLog(`getLocalRemoteNames: retrieveHostConfig failed: ${e.message}`, "forkDevWorker", "warn");
return [];
}
const { mapRemotesToDownload } = hostConfig;
return Object.keys(mapRemotesToDownload).reduce((sum, remoteModuleName) => {
const remoteInfo = mapRemotesToDownload[remoteModuleName];
const name = encodeNameIdentifier ? decodeName(remoteInfo.name, encodeNameIdentifier) : remoteInfo.name;
const ip = getIpFromEntry(remoteInfo.url, getIPV4());
if (!ip) return sum;
sum.push({
name,
entry: remoteInfo.url,
ip
});
return sum;
}, []);
}
async function updateCallback({ updateMode, name, remoteTypeTarPath, remoteInfo, once }) {
const { disableHotTypesReload, disableLiveReload } = cacheOptions || {};
fileLog(`sync remote module ${name}, types to ${cacheOptions?.name},typesManager.updateTypes run`, "forkDevWorker", "info");
if (!disableLiveReload && moduleServer) moduleServer.update({
updateKind: UpdateKind.RELOAD_PAGE,
updateMode: UpdateMode.PASSIVE
});
if (!disableHotTypesReload && typesManager) await typesManager.updateTypes({
updateMode,
remoteName: name,
remoteTarPath: remoteTypeTarPath,
remoteInfo,
once
});
}
async function forkDevWorker(options, action) {
if (!typesManager) {
const { name, remote, host, extraOptions } = options;
typesManager = new (getDTSManagerConstructor(remote?.implementation))({
remote,
host,
extraOptions
});
if (!options.disableHotTypesReload && remote) {
const { remoteOptions, tsConfig } = retrieveRemoteConfig(remote);
const mfTypesZipPath = retrieveTypesZipPath(retrieveMfTypesPath(tsConfig, remoteOptions), remoteOptions);
await Promise.all([createHttpServer({ typeTarPath: mfTypesZipPath }).then((res) => {
serverAddress = res.serverAddress;
}), typesManager.generateTypes()]).catch((err) => {
fileLog(`${name} module generateTypes done, localServerAddress: ${JSON.stringify(err)}`, "forkDevWorker", "error");
});
fileLog(`${name} module generateTypes done, localServerAddress: ${serverAddress}`, "forkDevWorker", "info");
}
moduleServer = new ModuleFederationDevServer({
name,
remotes: getLocalRemoteNames(host, extraOptions?.["encodeNameIdentifier"]),
updateCallback,
remoteTypeTarPath: `${serverAddress}/${DEFAULT_TAR_NAME}`
});
cacheOptions = options;
}
if (action === "update" && cacheOptions) {
fileLog(`remoteModule ${cacheOptions.name} receive devWorker update, start typesManager.updateTypes `, "forkDevWorker", "info");
if (!cacheOptions.disableLiveReload) moduleServer?.update({
updateKind: UpdateKind.RELOAD_PAGE,
updateMode: UpdateMode.POSITIVE
});
if (!cacheOptions.disableHotTypesReload) typesManager?.updateTypes({
updateMode: UpdateMode.POSITIVE,
remoteName: cacheOptions.name
}).then(() => {
moduleServer?.update({
updateKind: UpdateKind.UPDATE_TYPE,
updateMode: UpdateMode.POSITIVE
});
});
}
}
process.on("message", (message) => {
handleDevWorkerMessage(message, {
moduleServer,
log: fileLog
});
});
exposeRpc(forkDevWorker);
//#endregion
export { forkDevWorker };

View File

@@ -0,0 +1,14 @@
import { n as RpcGMCallTypes, r as generateTypes, t as exposeRpc } from "./expose-rpc-BgxOTFXQ.mjs";
import "./Broker-z82OgzMe.mjs";
//#region src/core/lib/forkGenerateDts.ts
async function forkGenerateDts(options) {
return generateTypes(options);
}
process.on("message", (message) => {
if (message.type === RpcGMCallTypes.EXIT) process.exit(0);
});
exposeRpc(forkGenerateDts);
//#endregion
export { forkGenerateDts };

View File

@@ -0,0 +1,504 @@
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 };

View File

@@ -0,0 +1,22 @@
import { s as fileLog, t as Broker } from "./Broker-z82OgzMe.mjs";
//#region src/server/broker/startBroker.ts
let broker;
function getBroker() {
return broker;
}
async function startBroker() {
if (getBroker()) return;
broker = new Broker();
await broker.start();
process.send?.("ready");
}
process.on("message", (message) => {
if (message === "start") {
fileLog(`startBroker... ${process.pid}`, "StartBroker", "info");
startBroker();
}
});
//#endregion
export { getBroker };

View File

@@ -0,0 +1,13 @@
//#region src/dev-worker/utils.ts
const DEFAULT_LOCAL_IPS = ["localhost", "127.0.0.1"];
function getIpFromEntry(entry, ipv4) {
let ip;
entry.replace(/https?:\/\/([0-9|.]+|localhost):/, (str, matched) => {
ip = matched;
return str;
});
if (ip) return DEFAULT_LOCAL_IPS.includes(ip) ? ipv4 : ip;
}
//#endregion
export { getIpFromEntry as t };

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
import { a as DTSManagerOptions } from "./DtsWorker-Dtem3-FM.js";
//#region src/dev-worker/DevWorker.d.ts
interface DevWorkerOptions extends DTSManagerOptions {
name: string;
disableLiveReload?: boolean;
disableHotTypesReload?: boolean;
}
//#endregion
//#region src/dev-worker/forkDevWorker.d.ts
interface Options extends DevWorkerOptions {
name: string;
}
declare function forkDevWorker(options: Options, action?: string): Promise<void>;
//#endregion
export { forkDevWorker };

View File

@@ -0,0 +1,114 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_Action = require('./Action-CzhPMw2i.js');
const require_Broker = require('./Broker-DRFgFvXI.js');
const require_expose_rpc = require('./expose-rpc-mEaCWCcd.js');
require('./consumeTypes-CFK17Cck.js');
require('./core.js');
const require_utils = require('./utils-7KqCZHbb.js');
let _module_federation_sdk = require("@module-federation/sdk");
//#region src/dev-worker/handleWorkerMessage.ts
function handleDevWorkerMessage(message, options = {}) {
const { moduleServer, processExit = process.exit, pid = process.pid, log = () => void 0 } = options;
log(`ChildProcess(${pid}), message: ${JSON.stringify(message)} `, "forkDevWorker", "info");
if (message.type === require_expose_rpc.RpcGMCallTypes.EXIT) {
log(`ChildProcess(${pid}) SIGTERM, Federation DevServer will exit...`, "forkDevWorker", "error");
moduleServer?.exit();
processExit(0);
}
}
//#endregion
//#region src/dev-worker/forkDevWorker.ts
let typesManager, serverAddress, moduleServer, cacheOptions;
function getLocalRemoteNames(options, encodeNameIdentifier) {
if (!options) return [];
let hostConfig;
try {
hostConfig = require_expose_rpc.retrieveHostConfig(options);
} catch (e) {
require_Broker.fileLog(`getLocalRemoteNames: retrieveHostConfig failed: ${e.message}`, "forkDevWorker", "warn");
return [];
}
const { mapRemotesToDownload } = hostConfig;
return Object.keys(mapRemotesToDownload).reduce((sum, remoteModuleName) => {
const remoteInfo = mapRemotesToDownload[remoteModuleName];
const name = encodeNameIdentifier ? (0, _module_federation_sdk.decodeName)(remoteInfo.name, encodeNameIdentifier) : remoteInfo.name;
const ip = require_utils.getIpFromEntry(remoteInfo.url, require_Broker.getIPV4());
if (!ip) return sum;
sum.push({
name,
entry: remoteInfo.url,
ip
});
return sum;
}, []);
}
async function updateCallback({ updateMode, name, remoteTypeTarPath, remoteInfo, once }) {
const { disableHotTypesReload, disableLiveReload } = cacheOptions || {};
require_Broker.fileLog(`sync remote module ${name}, types to ${cacheOptions?.name},typesManager.updateTypes run`, "forkDevWorker", "info");
if (!disableLiveReload && moduleServer) moduleServer.update({
updateKind: require_Broker.UpdateKind.RELOAD_PAGE,
updateMode: require_Action.UpdateMode.PASSIVE
});
if (!disableHotTypesReload && typesManager) await typesManager.updateTypes({
updateMode,
remoteName: name,
remoteTarPath: remoteTypeTarPath,
remoteInfo,
once
});
}
async function forkDevWorker(options, action) {
if (!typesManager) {
const { name, remote, host, extraOptions } = options;
typesManager = new (require_expose_rpc.getDTSManagerConstructor(remote?.implementation))({
remote,
host,
extraOptions
});
if (!options.disableHotTypesReload && remote) {
const { remoteOptions, tsConfig } = require_expose_rpc.retrieveRemoteConfig(remote);
const mfTypesZipPath = require_expose_rpc.retrieveTypesZipPath(require_expose_rpc.retrieveMfTypesPath(tsConfig, remoteOptions), remoteOptions);
await Promise.all([require_expose_rpc.createHttpServer({ typeTarPath: mfTypesZipPath }).then((res) => {
serverAddress = res.serverAddress;
}), typesManager.generateTypes()]).catch((err) => {
require_Broker.fileLog(`${name} module generateTypes done, localServerAddress: ${JSON.stringify(err)}`, "forkDevWorker", "error");
});
require_Broker.fileLog(`${name} module generateTypes done, localServerAddress: ${serverAddress}`, "forkDevWorker", "info");
}
moduleServer = new require_expose_rpc.ModuleFederationDevServer({
name,
remotes: getLocalRemoteNames(host, extraOptions?.["encodeNameIdentifier"]),
updateCallback,
remoteTypeTarPath: `${serverAddress}/${require_Action.DEFAULT_TAR_NAME}`
});
cacheOptions = options;
}
if (action === "update" && cacheOptions) {
require_Broker.fileLog(`remoteModule ${cacheOptions.name} receive devWorker update, start typesManager.updateTypes `, "forkDevWorker", "info");
if (!cacheOptions.disableLiveReload) moduleServer?.update({
updateKind: require_Broker.UpdateKind.RELOAD_PAGE,
updateMode: require_Action.UpdateMode.POSITIVE
});
if (!cacheOptions.disableHotTypesReload) typesManager?.updateTypes({
updateMode: require_Action.UpdateMode.POSITIVE,
remoteName: cacheOptions.name
}).then(() => {
moduleServer?.update({
updateKind: require_Broker.UpdateKind.UPDATE_TYPE,
updateMode: require_Action.UpdateMode.POSITIVE
});
});
}
}
process.on("message", (message) => {
handleDevWorkerMessage(message, {
moduleServer,
log: require_Broker.fileLog
});
});
require_expose_rpc.exposeRpc(forkDevWorker);
//#endregion
exports.forkDevWorker = forkDevWorker;

View File

@@ -0,0 +1,6 @@
import { n as DtsWorkerOptions } from "./DtsWorker-Dtem3-FM.js";
//#region src/core/lib/forkGenerateDts.d.ts
declare function forkGenerateDts(options: DtsWorkerOptions): Promise<void>;
//#endregion
export { forkGenerateDts };

View File

@@ -0,0 +1,15 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
require('./Broker-DRFgFvXI.js');
const require_expose_rpc = require('./expose-rpc-mEaCWCcd.js');
//#region src/core/lib/forkGenerateDts.ts
async function forkGenerateDts(options) {
return require_expose_rpc.generateTypes(options);
}
process.on("message", (message) => {
if (message.type === require_expose_rpc.RpcGMCallTypes.EXIT) process.exit(0);
});
require_expose_rpc.exposeRpc(forkGenerateDts);
//#endregion
exports.forkGenerateDts = forkGenerateDts;

View File

@@ -0,0 +1,117 @@
(function() {
//#region src/server/constant.ts
const DEFAULT_WEB_SOCKET_PORT = 16322;
const WEB_SOCKET_CONNECT_MAGIC_ID = "1hpzW-zo2z-o8io-gfmV1-2cb1d82";
//#endregion
//#region src/server/message/Message.ts
var Message = class {
constructor(type, kind) {
this.type = type;
this.kind = kind;
this.time = Date.now();
}
};
//#endregion
//#region src/server/message/Action/Action.ts
let ActionKind = /* @__PURE__ */ function(ActionKind) {
ActionKind["ADD_SUBSCRIBER"] = "ADD_SUBSCRIBER";
ActionKind["EXIT_SUBSCRIBER"] = "EXIT_SUBSCRIBER";
ActionKind["ADD_PUBLISHER"] = "ADD_PUBLISHER";
ActionKind["UPDATE_PUBLISHER"] = "UPDATE_PUBLISHER";
ActionKind["NOTIFY_SUBSCRIBER"] = "NOTIFY_SUBSCRIBER";
ActionKind["EXIT_PUBLISHER"] = "EXIT_PUBLISHER";
ActionKind["ADD_WEB_CLIENT"] = "ADD_WEB_CLIENT";
ActionKind["NOTIFY_WEB_CLIENT"] = "NOTIFY_WEB_CLIENT";
ActionKind["FETCH_TYPES"] = "FETCH_TYPES";
ActionKind["ADD_DYNAMIC_REMOTE"] = "ADD_DYNAMIC_REMOTE";
return ActionKind;
}({});
var Action = class extends Message {
constructor(content, kind) {
super("Action", kind);
const { payload } = content;
this.payload = payload;
}
};
//#endregion
//#region src/server/message/Action/AddWebClient.ts
var AddWebClientAction = class extends Action {
constructor(payload) {
super({ payload }, ActionKind.ADD_WEB_CLIENT);
}
};
//#endregion
//#region src/server/message/API/API.ts
let APIKind = /* @__PURE__ */ function(APIKind) {
APIKind["UPDATE_SUBSCRIBER"] = "UPDATE_SUBSCRIBER";
APIKind["RELOAD_WEB_CLIENT"] = "RELOAD_WEB_CLIENT";
APIKind["FETCH_TYPES"] = "FETCH_TYPES";
return APIKind;
}({});
//#endregion
//#region ../../node_modules/.pnpm/isomorphic-ws@5.0.0_ws@8.18.0/node_modules/isomorphic-ws/browser.js
var ws = null;
if (typeof WebSocket !== "undefined") ws = WebSocket;
else if (typeof MozWebSocket !== "undefined") ws = MozWebSocket;
else if (typeof global !== "undefined") ws = global.WebSocket || global.MozWebSocket;
else if (typeof window !== "undefined") ws = window.WebSocket || window.MozWebSocket;
else if (typeof self !== "undefined") ws = self.WebSocket || self.MozWebSocket;
var browser_default = ws;
//#endregion
//#region src/server/createWebsocket.ts
function createWebsocket() {
return new browser_default(`ws://127.0.0.1:${DEFAULT_WEB_SOCKET_PORT}?WEB_SOCKET_CONNECT_MAGIC_ID=${WEB_SOCKET_CONNECT_MAGIC_ID}`);
}
//#endregion
//#region src/server/WebClient.ts
var WebClient = class {
constructor(options) {
this._webSocket = null;
this._name = options.name;
this.logPrefix = options.logPrefix || "";
this._connect();
}
_connect() {
console.log(`${this.logPrefix}Trying to connect to {cyan ws://127.0.0.1:${DEFAULT_WEB_SOCKET_PORT}}...}`);
this._webSocket = createWebsocket();
this._webSocket.onopen = () => {
console.log(`${this.logPrefix}Connected to {cyan ws://127.0.0.1:${DEFAULT_WEB_SOCKET_PORT}} success!`);
const startWebClient = new AddWebClientAction({ name: this._name });
this._webSocket && this._webSocket.send(JSON.stringify(startWebClient));
};
this._webSocket.onmessage = (message) => {
console.log(message);
const parsedMessage = JSON.parse(message.data.toString());
if (parsedMessage.type === "API") {
if (parsedMessage.kind === APIKind.RELOAD_WEB_CLIENT) {
const { payload: { name } } = parsedMessage;
if (name !== this._name) return;
this._reload();
}
}
};
this._webSocket.onerror = (err) => {
console.error(`${this.logPrefix}err: ${err}`);
};
}
_reload() {
console.log(`${this.logPrefix}reload`);
location.reload();
}
};
//#endregion
//#region src/server/launchWebClient.ts
new WebClient(__WEB_CLIENT_OPTIONS__);
//#endregion
})();

View File

@@ -0,0 +1,67 @@
import { a as DTSManagerOptions } from "./DtsWorker-Dtem3-FM.js";
import { d as isTSProject } from "./constant-BwEkyidO.js";
import { moduleFederationPlugin } from "@module-federation/sdk";
//#region src/plugins/DtsPlugin.d.ts
declare const normalizeDtsOptions: (options: moduleFederationPlugin.ModuleFederationPluginOptions, context: string, defaultOptions?: {
defaultGenerateOptions?: moduleFederationPlugin.DtsRemoteOptions;
defaultConsumeOptions?: moduleFederationPlugin.DtsHostOptions;
}) => false | moduleFederationPlugin.PluginDtsOptions;
declare class DtsPlugin implements WebpackPluginInstance {
options: moduleFederationPlugin.ModuleFederationPluginOptions;
clonedOptions: moduleFederationPlugin.ModuleFederationPluginOptions;
constructor(options: moduleFederationPlugin.ModuleFederationPluginOptions);
apply(compiler: Compiler): void;
addRuntimePlugins(): void;
}
//#endregion
//#region src/plugins/ConsumeTypesPlugin.d.ts
declare const normalizeConsumeTypesOptions: ({
context,
dtsOptions,
pluginOptions
}: {
context?: string;
dtsOptions: moduleFederationPlugin.PluginDtsOptions;
pluginOptions: moduleFederationPlugin.ModuleFederationPluginOptions;
}) => {
host: {
typesFolder?: string;
abortOnError?: boolean;
remoteTypesFolder?: string;
deleteTypesFolder?: boolean;
maxRetries?: number;
consumeAPITypes?: boolean;
runtimePkgs?: string[];
remoteTypeUrls?: (() => Promise<moduleFederationPlugin.RemoteTypeUrls>) | moduleFederationPlugin.RemoteTypeUrls;
timeout?: number;
family?: 4 | 6;
typesOnBuild?: boolean;
implementation: string;
context: string;
moduleFederationConfig: moduleFederationPlugin.ModuleFederationPluginOptions;
};
extraOptions: Record<string, any>;
displayErrorInTerminal: boolean;
};
declare const consumeTypesAPI: (dtsManagerOptions: DTSManagerOptions, cb?: (options: moduleFederationPlugin.RemoteTypeUrls) => void) => Promise<void>;
//#endregion
//#region src/plugins/GenerateTypesPlugin.d.ts
declare const normalizeGenerateTypesOptions: ({
context,
outputDir,
dtsOptions,
pluginOptions
}: {
context?: string;
outputDir?: string;
dtsOptions: moduleFederationPlugin.PluginDtsOptions;
pluginOptions: moduleFederationPlugin.ModuleFederationPluginOptions;
}) => DTSManagerOptions;
declare const generateTypesAPI: ({
dtsManagerOptions
}: {
dtsManagerOptions: DTSManagerOptions;
}) => Promise<void>;
//#endregion
export { DtsPlugin, consumeTypesAPI, generateTypesAPI, isTSProject, normalizeConsumeTypesOptions, normalizeDtsOptions, normalizeGenerateTypesOptions };

View File

@@ -0,0 +1,512 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_Action = require('./Action-CzhPMw2i.js');
const require_Broker = require('./Broker-DRFgFvXI.js');
const require_expose_rpc = require('./expose-rpc-mEaCWCcd.js');
const require_consumeTypes = require('./consumeTypes-CFK17Cck.js');
require('./core.js');
let fs = require("fs");
fs = require_Action.__toESM(fs);
let path = require("path");
path = require_Action.__toESM(path);
let fs_promises = require("fs/promises");
let _module_federation_sdk = require("@module-federation/sdk");
//#region src/dev-worker/DevWorker.ts
var DevWorker = class {
constructor(options) {
this._options = require_expose_rpc.cloneDeepOptions(options);
this.removeUnSerializationOptions();
this._rpcWorker = require_consumeTypes.createRpcWorker(path.default.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: require_expose_rpc.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 (0, fs_promises.rm)(path.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.default.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.default.dirname(filePath);
fs.default.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.default.readFileSync(path.default.join(__dirname, "./iife/launch-web-client.iife.js")).toString("utf-8").replace(require_Action.WEB_CLIENT_OPTIONS_IDENTIFIER, JSON.stringify(options));
fs.default.writeFileSync(filePath, liveReloadEntryWithOptions);
}
_stopWhenSIGTERMOrSIGINT() {
process.on("SIGTERM", () => {
require_Broker.logger.info(`${this._options.name} Process(${process.pid}) SIGTERM, mf server will exit...`);
this._exit(PROCESS_EXIT_CODE.SUCCESS);
});
process.on("SIGINT", () => {
require_Broker.logger.info(`${this._options.name} Process(${process.pid}) SIGINT, mf server will exit...`);
this._exit(PROCESS_EXIT_CODE.SUCCESS);
});
}
_handleUnexpectedExit() {
process.on("unhandledRejection", (error) => {
require_Broker.logger.error(error);
require_Broker.logger.error(`Process(${process.pid}) unhandledRejection, mf server will exit...`);
this._exit(PROCESS_EXIT_CODE.FAILURE);
});
process.on("uncaughtException", (error) => {
require_Broker.logger.error(error);
require_Broker.logger.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 = (0, _module_federation_sdk.normalizeOptions)(true, {
disableLiveReload: true,
disableHotTypesReload: false,
disableDynamicRemoteTypeHints: false
}, "mfOptions.dev")(dev);
if (!isDev() || normalizedDev === false) return;
new compiler.webpack.DefinePlugin({ FEDERATION_IPV4: JSON.stringify(require_Broker.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.default.resolve(__dirname, "dynamic-remote-type-hints-plugin.js"));
}
if (!normalizedDev.disableLiveReload) {
const TEMP_DIR = path.default.join(`${process.cwd()}/node_modules`, _module_federation_sdk.TEMP_DIR);
const filepath = path.default.join(TEMP_DIR, `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 = (0, _module_federation_sdk.normalizeOptions)(require_expose_rpc.isTSProject(dts, compiler.context), {
generateTypes: defaultGenerateTypes,
consumeTypes: defaultConsumeTypes,
extraOptions: {},
displayErrorInTerminal: this.dtsOptions?.displayErrorInTerminal
}, "mfOptions.dts")(dts);
const normalizedGenerateTypes = (0, _module_federation_sdk.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 = (0, _module_federation_sdk.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 = (0, _module_federation_sdk.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
};
require_expose_rpc.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) => {
require_consumeTypes.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;
}
_module_federation_sdk.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;
_module_federation_sdk.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 = (0, _module_federation_sdk.normalizeOptions)(true, DEFAULT_GENERATE_TYPES, "mfOptions.dts.generateTypes")(dtsOptions.generateTypes);
if (!normalizedGenerateTypes) return;
const normalizedConsumeTypes = (0, _module_federation_sdk.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;
require_expose_rpc.validateOptions(finalOptions.remote);
return finalOptions;
};
const getGenerateTypesFn = (dtsManagerOptions) => {
let fn = require_expose_rpc.generateTypes;
if (dtsManagerOptions.remote.compileInChildProcess) fn = require_consumeTypes.generateTypesInChildProcess;
return fn;
};
const generateTypesAPI = ({ dtsManagerOptions }) => {
return getGenerateTypesFn(dtsManagerOptions)(dtsManagerOptions).then(async () => {
await callAfterGenerateHook({
dtsManagerOptions,
generatedTypes: require_expose_rpc.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) _module_federation_sdk.logger.error(error);
return;
}
throw error;
}
};
const WINDOWS_ABSOLUTE_PATH_REGEXP = /^[a-zA-Z]:[\\/]/;
const isSafeRelativePath = (relativePath) => {
return Boolean(relativePath) && !relativePath.startsWith("..") && !path.default.isAbsolute(relativePath) && !WINDOWS_ABSOLUTE_PATH_REGEXP.test(relativePath);
};
const resolveEmitAssetName = ({ compilerOutputPath, assetPath, fallbackName }) => {
if (!assetPath) return fallbackName;
const relativePath = path.default.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.default.resolve(context, outputDir);
const emitTypesFiles = async (compilation) => {
try {
const { zipTypesPath, apiTypesPath, zipName, apiFileName } = require_expose_rpc.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;
}
_module_federation_sdk.logger.debug("start generating types...");
await generateTypesAPI({ dtsManagerOptions });
_module_federation_sdk.logger.debug("generate types success!");
if (isProd) {
if (zipTypesPath && !compilation.getAsset(emitZipName) && fs.default.existsSync(zipTypesPath)) compilation.emitAsset(emitZipName, new compiler.webpack.sources.RawSource(fs.default.readFileSync(zipTypesPath)));
if (apiTypesPath && !compilation.getAsset(emitApiFileName) && fs.default.existsSync(apiTypesPath)) compilation.emitAsset(emitApiFileName, new compiler.webpack.sources.RawSource(fs.default.readFileSync(apiTypesPath)));
callback();
} else {
const isEEXIST = (err) => {
return err.code == "EEXIST";
};
if (zipTypesPath && fs.default.existsSync(zipTypesPath)) {
const zipContent = fs.default.readFileSync(zipTypesPath);
const zipOutputPath = path.default.join(compiler.outputPath, emitZipName);
await new Promise((resolve, reject) => {
compiler.outputFileSystem.mkdir(path.default.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.default.existsSync(apiTypesPath)) {
const apiContent = fs.default.readFileSync(apiTypesPath);
const apiOutputPath = path.default.join(compiler.outputPath, emitApiFileName);
await new Promise((resolve, reject) => {
compiler.outputFileSystem.mkdir(path.default.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);
_module_federation_sdk.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 (0, _module_federation_sdk.normalizeOptions)(require_expose_rpc.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
exports.DtsPlugin = DtsPlugin;
exports.consumeTypesAPI = consumeTypesAPI;
exports.generateTypesAPI = generateTypesAPI;
exports.isTSProject = require_expose_rpc.isTSProject;
exports.normalizeConsumeTypesOptions = normalizeConsumeTypesOptions;
exports.normalizeDtsOptions = normalizeDtsOptions;
exports.normalizeGenerateTypesOptions = normalizeGenerateTypesOptions;

View File

@@ -0,0 +1,44 @@
//#region src/server/broker/Broker.d.ts
declare class Broker {
static readonly WEB_SOCKET_CONNECT_MAGIC_ID = "1hpzW-zo2z-o8io-gfmV1-2cb1d82";
static readonly DEFAULT_WEB_SOCKET_PORT = 16322;
static readonly DEFAULT_SECURE_WEB_SOCKET_PORT = 16324;
static readonly DEFAULT_WAITING_TIME: number;
private _publisherMap;
private _webClientMap;
private _webSocketServer?;
private _secureWebSocketServer?;
private _tmpSubscriberShelter;
private _scheduleJob;
constructor();
get hasPublishers(): boolean;
private _startWsServer;
private _takeAction;
private _addPublisher;
private _updatePublisher;
private _fetchTypes;
private _addDynamicRemote;
private _addSubscriber;
private _removeSubscriber;
private _removePublisher;
private _addWebClient;
private _notifyWebClient;
private _addTmpSubScriberRelation;
private _getTmpSubScribers;
private _consumeTmpSubScribers;
private _clearTmpSubScriberRelation;
private _clearTmpSubScriberRelations;
private _disconnect;
private _setSchedule;
private _clearSchedule;
private _stopWhenSIGTERMOrSIGINT;
private _handleUnexpectedExit;
start(): Promise<void>;
exit(): void;
broadcast(message: unknown): void;
}
//#endregion
//#region src/server/broker/startBroker.d.ts
declare function getBroker(): Broker | undefined;
//#endregion
export { getBroker };

View File

@@ -0,0 +1,23 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_Broker = require('./Broker-DRFgFvXI.js');
//#region src/server/broker/startBroker.ts
let broker;
function getBroker() {
return broker;
}
async function startBroker() {
if (getBroker()) return;
broker = new require_Broker.Broker();
await broker.start();
process.send?.("ready");
}
process.on("message", (message) => {
if (message === "start") {
require_Broker.fileLog(`startBroker... ${process.pid}`, "StartBroker", "info");
startBroker();
}
});
//#endregion
exports.getBroker = getBroker;

View File

@@ -0,0 +1,19 @@
//#region src/dev-worker/utils.ts
const DEFAULT_LOCAL_IPS = ["localhost", "127.0.0.1"];
function getIpFromEntry(entry, ipv4) {
let ip;
entry.replace(/https?:\/\/([0-9|.]+|localhost):/, (str, matched) => {
ip = matched;
return str;
});
if (ip) return DEFAULT_LOCAL_IPS.includes(ip) ? ipv4 : ip;
}
//#endregion
Object.defineProperty(exports, 'getIpFromEntry', {
enumerable: true,
get: function () {
return getIpFromEntry;
}
});