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

21
node_modules/@module-federation/dts-plugin/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024-present danpeen(dapeen.feng)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1
node_modules/@module-federation/dts-plugin/README.md generated vendored Normal file
View File

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

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;
}
});

108
node_modules/@module-federation/dts-plugin/package.json generated vendored Normal file
View File

@@ -0,0 +1,108 @@
{
"name": "@module-federation/dts-plugin",
"version": "2.5.0",
"author": "hanric <hanric.zhang@gmail.com>",
"main": "./dist/index.js",
"module": "./dist/esm/index.mjs",
"types": "./dist/index.d.ts",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/module-federation/core.git",
"directory": "packages/dts-plugin"
},
"publishConfig": {
"access": "public"
},
"files": [
"dist/",
"README.md"
],
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/esm/index.mjs"
},
"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./core": {
"import": {
"types": "./dist/core.d.ts",
"default": "./dist/esm/core.mjs"
},
"require": {
"types": "./dist/core.d.ts",
"default": "./dist/core.js"
}
},
"./dynamic-remote-type-hints-plugin": {
"import": {
"types": "./dist/dynamic-remote-type-hints-plugin.d.ts",
"default": "./dist/esm/dynamic-remote-type-hints-plugin.mjs"
},
"require": {
"types": "./dist/dynamic-remote-type-hints-plugin.d.ts",
"default": "./dist/dynamic-remote-type-hints-plugin.js"
}
},
"./*": "./*"
},
"typesVersions": {
"*": {
".": [
"./dist/index.d.ts"
],
"core": [
"./dist/core.d.ts"
],
"dynamic-remote-type-hints-plugin": [
"./dist/dynamic-remote-type-hints-plugin.d.ts"
]
}
},
"dependencies": {
"adm-zip": "0.5.10",
"ansi-colors": "4.1.3",
"isomorphic-ws": "5.0.0",
"undici": "7.24.7",
"node-schedule": "2.1.1",
"ws": "8.18.0",
"@module-federation/managers": "2.5.0",
"@module-federation/third-party-dts-extractor": "2.5.0",
"@module-federation/sdk": "2.5.0",
"@module-federation/error-codes": "2.5.0"
},
"devDependencies": {
"@types/node-schedule": "2.1.7",
"@types/ws": "8.5.12",
"@vue/tsconfig": "^0.7.0",
"rimraf": "~6.0.1",
"vue": "^3.5.13",
"vue-tsc": "^2.2.10",
"directory-tree": "3.5.2",
"vitest": "1.6.0",
"webpack": "^5.104.1",
"@module-federation/runtime": "2.5.0"
},
"peerDependencies": {
"typescript": "^4.9.0 || ^5.0.0",
"vue-tsc": ">=1.0.24"
},
"peerDependenciesMeta": {
"vue-tsc": {
"optional": true
}
},
"scripts": {
"build": "tsdown --config ./tsdown.config.ts && sleep 1 && cp *.md ./dist",
"test": "node -e \"require('fs').rmSync('dist-test',{recursive:true,force:true,maxRetries:20,retryDelay:50})\" && pnpm run test-impl",
"test-impl": "pnpm exec vitest run --passWithNoTests --config vite.config.mts",
"lint": "ESLINT_USE_FLAT_CONFIG=false pnpm exec eslint --ignore-pattern node_modules \"**/*.ts\" \"package.json\"",
"build-debug": "FEDERATION_DEBUG=true pnpm run build",
"pre-release": "pnpm run test && pnpm run build"
}
}