@module-federation/dts-plugin 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,23 +36,22 @@ module.exports = __toCommonJS(forkDevWorker_exports);
36
36
 
37
37
  // packages/dts-plugin/src/core/configurations/remotePlugin.ts
38
38
  var import_fs2 = require("fs");
39
- var import_path4 = require("path");
39
+ var import_path5 = require("path");
40
40
  var import_managers2 = require("@module-federation/managers");
41
41
  var import_typescript2 = __toESM(require("typescript"));
42
42
 
43
43
  // packages/dts-plugin/src/core/lib/DTSManager.ts
44
- var import_ansi_colors3 = __toESM(require("ansi-colors"));
45
- var import_path3 = __toESM(require("path"));
44
+ var import_ansi_colors2 = __toESM(require("ansi-colors"));
45
+ var import_path4 = __toESM(require("path"));
46
46
  var import_promises = require("fs/promises");
47
47
  var import_fs = __toESM(require("fs"));
48
- var import_sdk2 = require("@module-federation/sdk");
48
+ var import_sdk4 = require("@module-federation/sdk");
49
49
  var import_lodash = __toESM(require("lodash.clonedeepwith"));
50
50
 
51
51
  // packages/dts-plugin/src/core/lib/archiveHandler.ts
52
52
  var import_adm_zip = __toESM(require("adm-zip"));
53
- var import_ansi_colors2 = __toESM(require("ansi-colors"));
54
53
  var import_axios = __toESM(require("axios"));
55
- var import_path2 = require("path");
54
+ var import_path3 = require("path");
56
55
 
57
56
  // packages/dts-plugin/src/core/lib/typeScriptCompiler.ts
58
57
  var import_ansi_colors = __toESM(require("ansi-colors"));
@@ -162,2207 +161,2209 @@ var compileTs = (mapComponentsToExpose, tsConfig, remoteOptions) => {
162
161
  }
163
162
  };
164
163
 
165
- // packages/dts-plugin/src/core/lib/archiveHandler.ts
166
- var retrieveTypesZipPath = (mfTypesPath, remoteOptions) => (0, import_path2.join)(
167
- mfTypesPath.replace(remoteOptions.typesFolder, ""),
168
- `${remoteOptions.typesFolder}.zip`
169
- );
170
- var createTypesArchive = async (tsConfig, remoteOptions) => {
171
- const mfTypesPath = retrieveMfTypesPath(tsConfig, remoteOptions);
172
- const zip = new import_adm_zip.default();
173
- zip.addLocalFolder(mfTypesPath);
174
- return zip.writeZipPromise(retrieveTypesZipPath(mfTypesPath, remoteOptions));
175
- };
176
- var downloadErrorLogger = (destinationFolder, fileToDownload) => (reason) => {
177
- throw {
178
- ...reason,
179
- message: `Network error: Unable to download federated mocks for '${destinationFolder}' from '${fileToDownload}' because '${reason.message}'`
180
- };
164
+ // packages/dts-plugin/src/server/message/Message.ts
165
+ var Message = class {
166
+ constructor(type, kind) {
167
+ this.type = type;
168
+ this.kind = kind;
169
+ this.time = Date.now();
170
+ }
181
171
  };
182
- var retrieveTypesArchiveDestinationPath = (hostOptions, destinationFolder) => {
183
- return (0, import_path2.resolve)(
184
- hostOptions.context,
185
- hostOptions.typesFolder,
186
- destinationFolder
187
- );
172
+
173
+ // packages/dts-plugin/src/server/message/API/API.ts
174
+ var API = class extends Message {
175
+ constructor(content, kind) {
176
+ super("API", kind);
177
+ const { code, payload } = content;
178
+ this.code = code;
179
+ this.payload = payload;
180
+ }
188
181
  };
189
- var downloadTypesArchive = (hostOptions) => {
190
- let retries = 0;
191
- return async ([destinationFolder, fileToDownload]) => {
192
- const destinationPath = retrieveTypesArchiveDestinationPath(
193
- hostOptions,
194
- destinationFolder
182
+
183
+ // packages/dts-plugin/src/server/message/API/UpdateSubscriber.ts
184
+ var UpdateSubscriberAPI = class extends API {
185
+ constructor(payload) {
186
+ super(
187
+ {
188
+ code: 0,
189
+ payload
190
+ },
191
+ "UPDATE_SUBSCRIBER" /* UPDATE_SUBSCRIBER */
195
192
  );
196
- while (retries++ < hostOptions.maxRetries) {
197
- try {
198
- const url = replaceLocalhost(fileToDownload);
199
- const response = await import_axios.default.get(url, { responseType: "arraybuffer" }).catch(downloadErrorLogger(destinationFolder, url));
200
- const zip = new import_adm_zip.default(Buffer.from(response.data));
201
- zip.extractAllTo(destinationPath, true);
202
- return [destinationFolder, destinationPath];
203
- } catch (error2) {
204
- if (isDebugMode()) {
205
- console.error(
206
- import_ansi_colors2.default.red(
207
- `Error during types archive download: ${(error2 == null ? void 0 : error2.message) || "unknown error"}`
208
- )
209
- );
210
- }
211
- if (retries >= hostOptions.maxRetries) {
212
- if (hostOptions.abortOnError !== false) {
213
- throw error2;
214
- }
215
- return void 0;
216
- }
217
- }
218
- }
219
- };
193
+ }
220
194
  };
221
195
 
222
- // packages/dts-plugin/src/core/configurations/hostPlugin.ts
223
- var import_sdk = require("@module-federation/sdk");
224
- var import_managers = require("@module-federation/managers");
225
- var defaultOptions = {
226
- typesFolder: "@mf-types",
227
- remoteTypesFolder: "@mf-types",
228
- deleteTypesFolder: true,
229
- maxRetries: 3,
230
- implementation: "",
231
- context: process.cwd(),
232
- abortOnError: true,
233
- consumeAPITypes: false
234
- };
235
- var buildZipUrl = (hostOptions, url) => {
236
- const remoteUrl = new URL(url);
237
- if (remoteUrl.href.includes(import_sdk.MANIFEST_EXT)) {
238
- return void 0;
196
+ // packages/dts-plugin/src/server/message/API/ReloadWebClient.ts
197
+ var ReloadWebClientAPI = class extends API {
198
+ constructor(payload) {
199
+ super(
200
+ {
201
+ code: 0,
202
+ payload
203
+ },
204
+ "RELOAD_WEB_CLIENT" /* RELOAD_WEB_CLIENT */
205
+ );
239
206
  }
240
- const pathnameWithoutEntry = remoteUrl.pathname.split("/").slice(0, -1).join("/");
241
- remoteUrl.pathname = `${pathnameWithoutEntry}/${hostOptions.remoteTypesFolder}.zip`;
242
- return remoteUrl.href;
243
207
  };
244
- var buildApiTypeUrl = (zipUrl) => {
245
- if (!zipUrl) {
246
- return void 0;
208
+
209
+ // packages/dts-plugin/src/server/utils/index.ts
210
+ var import_net = __toESM(require("net"));
211
+ var import_sdk2 = require("@module-federation/sdk");
212
+
213
+ // packages/dts-plugin/src/server/utils/logTransform.ts
214
+ var import_chalk = __toESM(require("chalk"));
215
+
216
+ // packages/dts-plugin/src/server/message/Log/Log.ts
217
+ var Log = class extends Message {
218
+ constructor(level, kind, ignoreVerbose = false) {
219
+ super("Log", kind);
220
+ this.ignoreVerbose = false;
221
+ this.level = level;
222
+ this.ignoreVerbose = ignoreVerbose;
247
223
  }
248
- return zipUrl.replace(".zip", ".d.ts");
249
- };
250
- var retrieveRemoteInfo = (options) => {
251
- const { hostOptions, remoteAlias, remote } = options;
252
- const parsedInfo = (0, import_sdk.parseEntry)(remote, void 0, "@");
253
- const url = "entry" in parsedInfo ? parsedInfo.entry : parsedInfo.name === remote ? remote : "";
254
- const zipUrl = url ? buildZipUrl(hostOptions, url) : "";
255
- return {
256
- name: parsedInfo.name || remoteAlias,
257
- url,
258
- zipUrl,
259
- apiTypeUrl: buildApiTypeUrl(zipUrl),
260
- alias: remoteAlias
261
- };
262
- };
263
- var resolveRemotes = (hostOptions) => {
264
- const parsedOptions = import_managers.utils.parseOptions(
265
- hostOptions.moduleFederationConfig.remotes || {},
266
- (item, key) => ({
267
- remote: Array.isArray(item) ? item[0] : item,
268
- key
269
- }),
270
- (item, key) => ({
271
- remote: Array.isArray(item.external) ? item.external[0] : item.external,
272
- key
273
- })
274
- );
275
- return parsedOptions.reduce(
276
- (accumulator, item) => {
277
- const { key, remote } = item[1];
278
- accumulator[key] = retrieveRemoteInfo({
279
- hostOptions,
280
- remoteAlias: key,
281
- remote
282
- });
283
- return accumulator;
284
- },
285
- {}
286
- );
287
224
  };
288
- var retrieveHostConfig = (options) => {
289
- validateOptions(options);
290
- const hostOptions = { ...defaultOptions, ...options };
291
- const mapRemotesToDownload = resolveRemotes(hostOptions);
292
- return {
293
- hostOptions,
294
- mapRemotesToDownload
295
- };
225
+
226
+ // packages/dts-plugin/src/server/message/Log/BrokerExitLog.ts
227
+ var BrokerExitLog = class extends Log {
228
+ constructor() {
229
+ super("LOG" /* LOG */, "BrokerExitLog" /* BrokerExitLog */);
230
+ }
296
231
  };
297
232
 
298
- // packages/dts-plugin/src/core/constant.ts
299
- var REMOTE_ALIAS_IDENTIFIER = "REMOTE_ALIAS_IDENTIFIER";
300
- var REMOTE_API_TYPES_FILE_NAME = "apis.d.ts";
301
- var HOST_API_TYPES_FILE_NAME = "index.d.ts";
233
+ // packages/dts-plugin/src/server/utils/log.ts
234
+ var import_sdk = require("@module-federation/sdk");
235
+ var log4js = __toESM(require("log4js"));
236
+ var import_chalk2 = __toESM(require("chalk"));
302
237
 
303
- // packages/dts-plugin/src/core/lib/DTSManager.ts
304
- var import_axios2 = __toESM(require("axios"));
305
- var DTSManager = class {
306
- constructor(options) {
307
- this.options = (0, import_lodash.default)(options, (_value, key) => {
308
- if (key === "manifest") {
309
- return false;
310
- }
311
- });
312
- this.runtimePkgs = [
313
- "@module-federation/runtime",
314
- "@module-federation/runtime-tools"
315
- ];
316
- this.loadedRemoteAPIAlias = [];
317
- this.remoteAliasMap = {};
318
- this.extraOptions = (options == null ? void 0 : options.extraOptions) || {};
319
- }
320
- generateAPITypes(mapComponentsToExpose) {
321
- const exposePaths = /* @__PURE__ */ new Set();
322
- const packageType = Object.keys(mapComponentsToExpose).reduce(
323
- (sum, exposeKey) => {
324
- const exposePath = import_path3.default.join(REMOTE_ALIAS_IDENTIFIER, exposeKey);
325
- exposePaths.add(`'${exposePath}'`);
326
- const curType = `T extends '${exposePath}' ? typeof import('${exposePath}') :`;
327
- sum = curType + sum;
328
- return sum;
329
- },
330
- "any;"
331
- );
332
- const exposePathKeys = [...exposePaths].join(" | ");
333
- return `
334
- export type RemoteKeys = ${exposePathKeys};
335
- type PackageType<T> = ${packageType}`;
238
+ // packages/dts-plugin/src/server/constant.ts
239
+ var DEFAULT_WEB_SOCKET_PORT = 16322;
240
+ var WEB_SOCKET_CONNECT_MAGIC_ID = "1hpzW-zo2z-o8io-gfmV1-2cb1d82";
241
+ var MF_SERVER_IDENTIFIER = "Module Federation Dev Server";
242
+ var DEFAULT_TAR_NAME = "@mf-types.zip";
243
+
244
+ // packages/dts-plugin/src/server/utils/log.ts
245
+ function fileLog(msg, module2, level) {
246
+ var _a, _b;
247
+ if (!((_a = process == null ? void 0 : process.env) == null ? void 0 : _a["FEDERATION_DEBUG"])) {
248
+ return;
336
249
  }
337
- async extractRemoteTypes(options) {
338
- const { remoteOptions, tsConfig } = options;
339
- if (!remoteOptions.extractRemoteTypes) {
340
- return;
341
- }
342
- let hasRemotes = false;
343
- const remotes = remoteOptions.moduleFederationConfig.remotes;
344
- if (remotes) {
345
- if (Array.isArray(remotes)) {
346
- hasRemotes = Boolean(remotes.length);
347
- } else if (typeof remotes === "object") {
348
- hasRemotes = Boolean(Object.keys(remotes).length);
349
- }
250
+ log4js.configure({
251
+ appenders: {
252
+ [module2]: { type: "file", filename: ".mf/typesGenerate.log" },
253
+ default: { type: "file", filename: ".mf/typesGenerate.log" }
254
+ },
255
+ categories: {
256
+ [module2]: { appenders: [module2], level: "error" },
257
+ default: { appenders: ["default"], level: "trace" }
350
258
  }
351
- const mfTypesPath = retrieveMfTypesPath(tsConfig, remoteOptions);
352
- if (hasRemotes) {
353
- const tempHostOptions = {
354
- moduleFederationConfig: remoteOptions.moduleFederationConfig,
355
- typesFolder: import_path3.default.join(mfTypesPath, "node_modules"),
356
- remoteTypesFolder: (remoteOptions == null ? void 0 : remoteOptions.hostRemoteTypesFolder) || remoteOptions.typesFolder,
357
- deleteTypesFolder: true,
358
- context: remoteOptions.context,
359
- implementation: remoteOptions.implementation,
360
- abortOnError: false
361
- };
362
- await this.consumeArchiveTypes(tempHostOptions);
363
- }
364
- }
365
- async generateTypes() {
366
- var _a;
367
- try {
368
- const { options } = this;
369
- if (!options.remote) {
370
- throw new Error(
371
- "options.remote is required if you want to generateTypes"
372
- );
373
- }
374
- const { remoteOptions, tsConfig, mapComponentsToExpose } = retrieveRemoteConfig(options.remote);
375
- if (!Object.keys(mapComponentsToExpose).length) {
376
- return;
377
- }
378
- this.extractRemoteTypes({
379
- remoteOptions,
380
- tsConfig,
381
- mapComponentsToExpose
259
+ });
260
+ const logger4 = log4js.getLogger(module2);
261
+ logger4.level = "debug";
262
+ (_b = logger4[level]) == null ? void 0 : _b.call(logger4, msg);
263
+ }
264
+ function error(error2, action, from) {
265
+ const err = error2 instanceof Error ? error2 : new Error(`${action} error`);
266
+ fileLog(`[${action}] error: ${err}`, from, "fatal");
267
+ return err.toString();
268
+ }
269
+
270
+ // packages/dts-plugin/src/server/utils/getIPV4.ts
271
+ var import_os = __toESM(require("os"));
272
+ var localIpv4 = "127.0.0.1";
273
+ var getIpv4Interfaces = () => {
274
+ try {
275
+ const interfaces = import_os.default.networkInterfaces();
276
+ const ipv4Interfaces = [];
277
+ Object.values(interfaces).forEach((detail) => {
278
+ detail == null ? void 0 : detail.forEach((detail2) => {
279
+ const familyV4Value = typeof detail2.family === "string" ? "IPv4" : 4;
280
+ if (detail2.family === familyV4Value && detail2.address !== localIpv4) {
281
+ ipv4Interfaces.push(detail2);
282
+ }
382
283
  });
383
- compileTs(mapComponentsToExpose, tsConfig, remoteOptions);
384
- await createTypesArchive(tsConfig, remoteOptions);
385
- let apiTypesPath = "";
386
- if (remoteOptions.generateAPITypes) {
387
- const apiTypes = this.generateAPITypes(mapComponentsToExpose);
388
- apiTypesPath = retrieveMfAPITypesPath(tsConfig, remoteOptions);
389
- import_fs.default.writeFileSync(apiTypesPath, apiTypes);
390
- }
391
- if (remoteOptions.deleteTypesFolder) {
392
- await (0, import_promises.rm)(retrieveMfTypesPath(tsConfig, remoteOptions), {
393
- recursive: true,
394
- force: true
395
- });
396
- }
397
- console.log(import_ansi_colors3.default.green("Federated types created correctly"));
398
- } catch (error2) {
399
- if (((_a = this.options.remote) == null ? void 0 : _a.abortOnError) === false) {
400
- console.error(
401
- import_ansi_colors3.default.red(`Unable to compile federated types, ${error2}`)
402
- );
403
- } else {
404
- throw error2;
405
- }
406
- }
284
+ });
285
+ return ipv4Interfaces;
286
+ } catch (_err) {
287
+ return [];
407
288
  }
408
- async requestRemoteManifest(remoteInfo) {
409
- try {
410
- if (!remoteInfo.url.includes(import_sdk2.MANIFEST_EXT)) {
411
- return remoteInfo;
412
- }
413
- const url = replaceLocalhost(remoteInfo.url);
414
- const res = await (0, import_axios2.default)({
415
- method: "get",
416
- url
289
+ };
290
+ var getIPV4 = () => {
291
+ const ipv4Interfaces = getIpv4Interfaces();
292
+ const ipv4Interface = ipv4Interfaces[0] || { address: localIpv4 };
293
+ return ipv4Interface.address;
294
+ };
295
+
296
+ // packages/dts-plugin/src/server/utils/index.ts
297
+ function getIdentifier(options) {
298
+ const { ip, name } = options;
299
+ return `mf ${import_sdk2.SEPARATOR}${name}${ip ? `${import_sdk2.SEPARATOR}${ip}` : ""}`;
300
+ }
301
+ function fib(n) {
302
+ let i = 2;
303
+ const res = [0, 1, 1];
304
+ while (i <= n) {
305
+ res[i] = res[i - 1] + res[i - 2];
306
+ i++;
307
+ }
308
+ return res[n];
309
+ }
310
+ function getFreePort() {
311
+ return new Promise((resolve4, reject) => {
312
+ const server = import_net.default.createServer();
313
+ server.unref();
314
+ server.on("error", reject);
315
+ server.listen(0, () => {
316
+ const { port } = server.address();
317
+ server.close(() => {
318
+ resolve4(port);
417
319
  });
418
- const manifestJson = res.data;
419
- if (!manifestJson.metaData.types.zip) {
420
- throw new Error(`Can not get ${remoteInfo.name}'s types archive url!`);
421
- }
422
- const addProtocol = (u) => {
423
- if (u.startsWith("//")) {
424
- return `https:${u}`;
425
- }
426
- return u;
427
- };
428
- const publicPath = "publicPath" in manifestJson.metaData ? manifestJson.metaData.publicPath : new Function(manifestJson.metaData.getPublicPath)();
429
- remoteInfo.zipUrl = new URL(
430
- import_path3.default.join(addProtocol(publicPath), manifestJson.metaData.types.zip)
431
- ).href;
432
- if (!manifestJson.metaData.types.api) {
433
- console.warn(`Can not get ${remoteInfo.name}'s api types url!`);
434
- remoteInfo.apiTypeUrl = "";
435
- return remoteInfo;
436
- }
437
- remoteInfo.apiTypeUrl = new URL(
438
- import_path3.default.join(addProtocol(publicPath), manifestJson.metaData.types.api)
439
- ).href;
440
- return remoteInfo;
441
- } catch (_err) {
442
- console.error(_err);
443
- return remoteInfo;
444
- }
320
+ });
321
+ });
322
+ }
323
+
324
+ // packages/dts-plugin/src/server/Publisher.ts
325
+ var Publisher = class {
326
+ constructor(ctx) {
327
+ this._name = ctx.name;
328
+ this._ip = ctx.ip;
329
+ this._remoteTypeTarPath = ctx.remoteTypeTarPath;
330
+ this._subscribers = /* @__PURE__ */ new Map();
445
331
  }
446
- async consumeTargetRemotes(hostOptions, remoteInfo) {
447
- if (!remoteInfo.zipUrl) {
448
- throw new Error(`Can not get ${remoteInfo.name}'s types archive url!`);
449
- }
450
- const typesDownloader = downloadTypesArchive(hostOptions);
451
- return typesDownloader([remoteInfo.alias, remoteInfo.zipUrl]);
332
+ get identifier() {
333
+ return getIdentifier({
334
+ name: this._name,
335
+ ip: this._ip
336
+ });
452
337
  }
453
- async downloadAPITypes(remoteInfo, destinationPath) {
454
- const { apiTypeUrl } = remoteInfo;
455
- if (!apiTypeUrl) {
456
- return;
457
- }
458
- try {
459
- const url = replaceLocalhost(apiTypeUrl);
460
- const res = await import_axios2.default.get(url);
461
- let apiTypeFile = res.data;
462
- apiTypeFile = apiTypeFile.replaceAll(
463
- REMOTE_ALIAS_IDENTIFIER,
464
- remoteInfo.alias
465
- );
466
- const filePath = import_path3.default.join(destinationPath, REMOTE_API_TYPES_FILE_NAME);
467
- import_fs.default.writeFileSync(filePath, apiTypeFile);
468
- this.loadedRemoteAPIAlias.push(remoteInfo.alias);
469
- } catch (err) {
470
- console.error(
471
- import_ansi_colors3.default.red(
472
- `Unable to download "${remoteInfo.name}" api types, ${err}`
473
- )
338
+ get name() {
339
+ return this._name;
340
+ }
341
+ get ip() {
342
+ return this._ip;
343
+ }
344
+ get remoteTypeTarPath() {
345
+ return this._remoteTypeTarPath;
346
+ }
347
+ get hasSubscribes() {
348
+ return Boolean(this._subscribers.size);
349
+ }
350
+ get subscribers() {
351
+ return this._subscribers;
352
+ }
353
+ addSubscriber(identifier, subscriber) {
354
+ fileLog(`${this.name} set subscriber: ${identifier}`, "Publisher", "info");
355
+ this._subscribers.set(identifier, subscriber);
356
+ }
357
+ removeSubscriber(identifier) {
358
+ if (this._subscribers.has(identifier)) {
359
+ fileLog(
360
+ `${this.name} removeSubscriber: ${identifier}`,
361
+ "Publisher",
362
+ "warn"
474
363
  );
364
+ this._subscribers.delete(identifier);
475
365
  }
476
366
  }
477
- consumeAPITypes(hostOptions) {
478
- if (!this.loadedRemoteAPIAlias.length) {
367
+ notifySubscriber(subscriberIdentifier, options) {
368
+ const subscriber = this._subscribers.get(subscriberIdentifier);
369
+ if (!subscriber) {
370
+ fileLog(
371
+ `[notifySubscriber] ${this.name} notifySubscriber: ${subscriberIdentifier}, does not exits`,
372
+ "Publisher",
373
+ "error"
374
+ );
479
375
  return;
480
376
  }
481
- const packageTypes = [];
482
- const remoteKeys = [];
483
- const importTypeStr = this.loadedRemoteAPIAlias.map((alias, index) => {
484
- const remoteKey = `RemoteKeys_${index}`;
485
- const packageType = `PackageType_${index}`;
486
- packageTypes.push(`T extends ${remoteKey} ? ${packageType}<T>`);
487
- remoteKeys.push(remoteKey);
488
- return `import type { PackageType as ${packageType},RemoteKeys as ${remoteKey} } from './${alias}/apis.d.ts';`;
489
- }).join("\n");
490
- const remoteKeysStr = `type RemoteKeys = ${remoteKeys.join(" | ")};`;
491
- const packageTypesStr = `type PackageType<T, Y=any> = ${[
492
- ...packageTypes,
493
- "Y"
494
- ].join(" :\n")} ;`;
495
- const pkgsDeclareStr = this.runtimePkgs.map((pkg) => {
496
- return `declare module "${pkg}" {
497
- ${remoteKeysStr}
498
- ${packageTypesStr}
499
- export function loadRemote<T extends RemoteKeys,Y>(packageName: T): Promise<PackageType<T, Y>>;
500
- export function loadRemote<T extends string,Y>(packageName: T): Promise<PackageType<T, Y>>;
501
- }`;
502
- }).join("\n");
503
- const fileStr = `${importTypeStr}
504
- ${pkgsDeclareStr}
505
- `;
506
- import_fs.default.writeFileSync(
507
- import_path3.default.join(
508
- hostOptions.context,
509
- hostOptions.typesFolder,
510
- HOST_API_TYPES_FILE_NAME
511
- ),
512
- fileStr
377
+ const api = new UpdateSubscriberAPI(options);
378
+ subscriber.send(JSON.stringify(api));
379
+ fileLog(
380
+ `[notifySubscriber] ${this.name} notifySubscriber: ${JSON.stringify(
381
+ subscriberIdentifier
382
+ )}, message: ${JSON.stringify(api)}`,
383
+ "Publisher",
384
+ "info"
513
385
  );
514
386
  }
515
- async consumeArchiveTypes(options) {
516
- const { hostOptions, mapRemotesToDownload } = retrieveHostConfig(options);
517
- if (hostOptions.deleteTypesFolder) {
518
- await (0, import_promises.rm)(hostOptions.typesFolder, {
519
- recursive: true,
520
- force: true
521
- }).catch(
522
- (error2) => console.error(
523
- import_ansi_colors3.default.red(`Unable to remove types folder, ${error2}`)
524
- )
525
- );
526
- }
527
- const downloadPromises = Object.entries(mapRemotesToDownload).map(
528
- async (item) => {
529
- const remoteInfo = item[1];
530
- if (!this.remoteAliasMap[remoteInfo.alias]) {
531
- const requiredRemoteInfo = await this.requestRemoteManifest(remoteInfo);
532
- this.remoteAliasMap[remoteInfo.alias] = requiredRemoteInfo;
533
- }
534
- return this.consumeTargetRemotes(
535
- hostOptions,
536
- this.remoteAliasMap[remoteInfo.alias]
537
- );
538
- }
539
- );
540
- const downloadPromisesResult = await Promise.allSettled(downloadPromises);
541
- return {
542
- hostOptions,
543
- downloadPromisesResult
544
- };
387
+ notifySubscribers(options) {
388
+ const api = new UpdateSubscriberAPI(options);
389
+ this.broadcast(api);
545
390
  }
546
- async consumeTypes() {
547
- var _a;
548
- try {
549
- const { options } = this;
550
- if (!options.host) {
551
- throw new Error("options.host is required if you want to consumeTypes");
552
- }
553
- const { mapRemotesToDownload } = retrieveHostConfig(options.host);
554
- if (!Object.keys(mapRemotesToDownload).length) {
555
- return;
556
- }
557
- const { downloadPromisesResult, hostOptions } = await this.consumeArchiveTypes(options.host);
558
- if (hostOptions.consumeAPITypes) {
559
- await Promise.all(
560
- downloadPromisesResult.map(async (item) => {
561
- if (item.status === "rejected" || !item.value) {
562
- return;
563
- }
564
- const [alias, destinationPath] = item.value;
565
- const remoteInfo = this.remoteAliasMap[alias];
566
- if (!remoteInfo) {
567
- return;
568
- }
569
- await this.downloadAPITypes(remoteInfo, destinationPath);
570
- })
571
- );
572
- this.consumeAPITypes(hostOptions);
573
- }
574
- console.log(import_ansi_colors3.default.green("Federated types extraction completed"));
575
- } catch (err) {
576
- if (((_a = this.options.host) == null ? void 0 : _a.abortOnError) === false) {
577
- console.error(
578
- import_ansi_colors3.default.red(`Unable to consume federated types, ${err}`)
391
+ broadcast(message) {
392
+ if (this.hasSubscribes) {
393
+ this._subscribers.forEach((subscriber, key) => {
394
+ fileLog(
395
+ `[BroadCast] ${this.name} notifySubscriber: ${key}, PID: ${process.pid}, message: ${JSON.stringify(message)}`,
396
+ "Publisher",
397
+ "info"
579
398
  );
580
- } else {
581
- throw err;
582
- }
583
- }
584
- }
585
- async updateTypes(options) {
586
- var _a, _b, _c;
587
- const { remoteName, updateMode } = options;
588
- const hostName = (_c = (_b = (_a = this.options) == null ? void 0 : _a.host) == null ? void 0 : _b.moduleFederationConfig) == null ? void 0 : _c.name;
589
- if (updateMode === "POSITIVE" /* POSITIVE */ && remoteName === hostName) {
590
- if (!this.options.remote) {
591
- return;
592
- }
593
- this.generateTypes();
399
+ subscriber.send(JSON.stringify(message));
400
+ });
594
401
  } else {
595
- const { remoteAliasMap } = this;
596
- if (!this.options.host) {
597
- return;
598
- }
599
- const { hostOptions, mapRemotesToDownload } = retrieveHostConfig(
600
- this.options.host
601
- );
602
- const loadedRemoteInfo = Object.values(remoteAliasMap).find(
603
- (i) => i.name === remoteName
402
+ fileLog(
403
+ `[BroadCast] ${this.name}'s subscribe is empty`,
404
+ "Publisher",
405
+ "warn"
604
406
  );
605
- if (!loadedRemoteInfo) {
606
- const remoteInfo = Object.values(mapRemotesToDownload).find((item) => {
607
- return item.name === remoteName;
608
- });
609
- if (remoteInfo) {
610
- if (!this.remoteAliasMap[remoteInfo.alias]) {
611
- const requiredRemoteInfo = await this.requestRemoteManifest(remoteInfo);
612
- this.remoteAliasMap[remoteInfo.alias] = requiredRemoteInfo;
613
- }
614
- await this.consumeTargetRemotes(
615
- hostOptions,
616
- this.remoteAliasMap[remoteInfo.alias]
617
- );
618
- }
619
- } else {
620
- await this.consumeTargetRemotes(hostOptions, loadedRemoteInfo);
621
- }
622
407
  }
623
408
  }
409
+ close() {
410
+ this._subscribers.forEach((_subscriber, identifier) => {
411
+ fileLog(
412
+ `[BroadCast] close ${this.name} remove: ${identifier}`,
413
+ "Publisher",
414
+ "warn"
415
+ );
416
+ this.removeSubscriber(identifier);
417
+ });
418
+ }
624
419
  };
625
420
 
626
- // packages/dts-plugin/src/core/lib/utils.ts
627
- var import_ansi_colors4 = __toESM(require("ansi-colors"));
628
- function getDTSManagerConstructor(implementation) {
629
- if (implementation) {
630
- const NewConstructor = require(implementation);
631
- return NewConstructor.default ? NewConstructor.default : NewConstructor;
421
+ // packages/dts-plugin/src/server/DevServer.ts
422
+ var import_isomorphic_ws2 = __toESM(require("isomorphic-ws"));
423
+
424
+ // packages/dts-plugin/src/server/broker/Broker.ts
425
+ var import_http = require("http");
426
+ var import_isomorphic_ws = __toESM(require("isomorphic-ws"));
427
+ var import_node_schedule = __toESM(require("node-schedule"));
428
+ var import_url = require("url");
429
+
430
+ // packages/dts-plugin/src/server/message/Action/Action.ts
431
+ var Action = class extends Message {
432
+ constructor(content, kind) {
433
+ super("Action", kind);
434
+ const { payload } = content;
435
+ this.payload = payload;
632
436
  }
633
- return DTSManager;
634
- }
635
- var validateOptions = (options) => {
636
- if (!options.moduleFederationConfig) {
637
- throw new Error("moduleFederationConfig is required");
437
+ };
438
+
439
+ // packages/dts-plugin/src/server/message/Action/AddPublisher.ts
440
+ var AddPublisherAction = class extends Action {
441
+ constructor(payload) {
442
+ super(
443
+ {
444
+ payload
445
+ },
446
+ "ADD_PUBLISHER" /* ADD_PUBLISHER */
447
+ );
638
448
  }
639
449
  };
640
- function replaceLocalhost(url) {
641
- return url.replace("localhost", "127.0.0.1");
642
- }
643
- function isDebugMode() {
644
- return Boolean(process.env["FEDERATION_DEBUG"]);
645
- }
646
450
 
647
- // packages/dts-plugin/src/core/configurations/remotePlugin.ts
648
- var defaultOptions2 = {
649
- tsConfigPath: "./tsconfig.json",
650
- typesFolder: "@mf-types",
651
- compiledTypesFolder: "compiled-types",
652
- hostRemoteTypesFolder: "@mf-types",
653
- deleteTypesFolder: true,
654
- additionalFilesToCompile: [],
655
- compilerInstance: "tsc",
656
- compileInChildProcess: false,
657
- implementation: "",
658
- generateAPITypes: false,
659
- context: process.cwd(),
660
- abortOnError: true,
661
- extractRemoteTypes: false,
662
- extractThirdParty: false
451
+ // packages/dts-plugin/src/server/message/Action/AddSubscriber.ts
452
+ var AddSubscriberAction = class extends Action {
453
+ constructor(payload) {
454
+ super(
455
+ {
456
+ payload
457
+ },
458
+ "ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */
459
+ );
460
+ }
663
461
  };
664
- var readTsConfig = ({
665
- tsConfigPath,
666
- typesFolder,
667
- compiledTypesFolder,
668
- context
669
- }) => {
670
- const resolvedTsConfigPath = (0, import_path4.resolve)(context, tsConfigPath);
671
- const readResult = import_typescript2.default.readConfigFile(
672
- resolvedTsConfigPath,
673
- import_typescript2.default.sys.readFile
674
- );
675
- if (readResult.error) {
676
- throw new Error(readResult.error.messageText.toString());
462
+
463
+ // packages/dts-plugin/src/server/message/Action/ExitSubscriber.ts
464
+ var ExitSubscriberAction = class extends Action {
465
+ constructor(payload) {
466
+ super(
467
+ {
468
+ payload
469
+ },
470
+ "EXIT_SUBSCRIBER" /* EXIT_SUBSCRIBER */
471
+ );
677
472
  }
678
- const configContent = import_typescript2.default.parseJsonConfigFileContent(
679
- readResult.config,
680
- import_typescript2.default.sys,
681
- (0, import_path4.dirname)(resolvedTsConfigPath)
682
- );
683
- const outDir = (0, import_path4.resolve)(
684
- context,
685
- configContent.options.outDir || "dist",
686
- typesFolder,
687
- compiledTypesFolder
688
- );
689
- return {
690
- ...configContent.options,
691
- emitDeclarationOnly: true,
692
- noEmit: false,
693
- declaration: true,
694
- outDir
695
- };
696
473
  };
697
- var TS_EXTENSIONS = ["ts", "tsx", "vue", "svelte"];
698
- var resolveWithExtension = (exposedPath, context) => {
699
- if ((0, import_path4.extname)(exposedPath)) {
700
- return (0, import_path4.resolve)(context, exposedPath);
474
+
475
+ // packages/dts-plugin/src/server/message/Action/ExitPublisher.ts
476
+ var ExitPublisherAction = class extends Action {
477
+ constructor(payload) {
478
+ super(
479
+ {
480
+ payload
481
+ },
482
+ "EXIT_PUBLISHER" /* EXIT_PUBLISHER */
483
+ );
701
484
  }
702
- for (const extension of TS_EXTENSIONS) {
703
- const exposedPathWithExtension = (0, import_path4.resolve)(
704
- context,
705
- `${exposedPath}.${extension}`
485
+ };
486
+
487
+ // packages/dts-plugin/src/server/message/Action/NotifyWebClient.ts
488
+ var NotifyWebClientAction = class extends Action {
489
+ constructor(payload) {
490
+ super(
491
+ {
492
+ payload
493
+ },
494
+ "NOTIFY_WEB_CLIENT" /* NOTIFY_WEB_CLIENT */
706
495
  );
707
- if ((0, import_fs2.existsSync)(exposedPathWithExtension)) {
708
- return exposedPathWithExtension;
709
- }
710
496
  }
711
- return void 0;
712
497
  };
713
- var resolveExposes = (remoteOptions) => {
714
- const parsedOptions = import_managers2.utils.parseOptions(
715
- remoteOptions.moduleFederationConfig.exposes || {},
716
- (item, key) => ({
717
- exposePath: Array.isArray(item) ? item[0] : item,
718
- key
719
- }),
720
- (item, key) => ({
721
- exposePath: Array.isArray(item.import) ? item.import[0] : item.import[0],
722
- key
723
- })
724
- );
725
- return parsedOptions.reduce(
726
- (accumulator, item) => {
727
- const { exposePath, key } = item[1];
728
- accumulator[key] = resolveWithExtension(exposePath, remoteOptions.context) || resolveWithExtension(
729
- (0, import_path4.join)(exposePath, "index"),
730
- remoteOptions.context
731
- ) || exposePath;
732
- return accumulator;
733
- },
734
- {}
735
- );
736
- };
737
- var retrieveRemoteConfig = (options) => {
738
- validateOptions(options);
739
- const remoteOptions = {
740
- ...defaultOptions2,
741
- ...options
742
- };
743
- const mapComponentsToExpose = resolveExposes(remoteOptions);
744
- const tsConfig = readTsConfig(remoteOptions);
745
- return {
746
- tsConfig,
747
- mapComponentsToExpose,
748
- remoteOptions
749
- };
750
- };
751
-
752
- // packages/dts-plugin/src/core/lib/DtsWorker.ts
753
- var import_lodash2 = __toESM(require("lodash.clonedeepwith"));
754
-
755
- // packages/dts-plugin/src/core/rpc/index.ts
756
- var rpc_exports = {};
757
- __export(rpc_exports, {
758
- RpcExitError: () => RpcExitError,
759
- RpcGMCallTypes: () => RpcGMCallTypes,
760
- createRpcWorker: () => createRpcWorker,
761
- exposeRpc: () => exposeRpc,
762
- getRpcWorkerData: () => getRpcWorkerData,
763
- wrapRpc: () => wrapRpc
764
- });
765
498
 
766
- // packages/dts-plugin/src/core/rpc/expose-rpc.ts
767
- var import_process = __toESM(require("process"));
768
-
769
- // packages/dts-plugin/src/core/rpc/types.ts
770
- var RpcGMCallTypes = /* @__PURE__ */ ((RpcGMCallTypes2) => {
771
- RpcGMCallTypes2["CALL"] = "mf_call";
772
- RpcGMCallTypes2["RESOLVE"] = "mf_resolve";
773
- RpcGMCallTypes2["REJECT"] = "mf_reject";
774
- RpcGMCallTypes2["EXIT"] = "mf_exit";
775
- return RpcGMCallTypes2;
776
- })(RpcGMCallTypes || {});
499
+ // packages/dts-plugin/src/server/message/Action/UpdatePublisher.ts
500
+ var UpdatePublisherAction = class extends Action {
501
+ constructor(payload) {
502
+ super(
503
+ {
504
+ payload
505
+ },
506
+ "UPDATE_PUBLISHER" /* UPDATE_PUBLISHER */
507
+ );
508
+ }
509
+ };
777
510
 
778
- // packages/dts-plugin/src/core/rpc/expose-rpc.ts
779
- function exposeRpc(fn) {
780
- const sendMessage = (message) => new Promise((resolve4, reject) => {
781
- if (!import_process.default.send) {
782
- reject(new Error(`Process ${import_process.default.pid} doesn't have IPC channels`));
783
- } else if (!import_process.default.connected) {
784
- reject(
785
- new Error(`Process ${import_process.default.pid} doesn't have open IPC channels`)
786
- );
787
- } else {
788
- import_process.default.send(message, void 0, void 0, (error2) => {
789
- if (error2) {
790
- reject(error2);
791
- } else {
792
- resolve4(void 0);
793
- }
794
- });
795
- }
796
- });
797
- const handleMessage = async (message) => {
798
- if (message.type === "mf_call" /* CALL */) {
799
- if (!import_process.default.send) {
800
- return;
801
- }
802
- let value, error2;
803
- try {
804
- value = await fn(...message.args);
805
- } catch (fnError) {
806
- error2 = fnError;
511
+ // packages/dts-plugin/src/server/broker/Broker.ts
512
+ var _Broker = class _Broker {
513
+ constructor() {
514
+ // 1.5h
515
+ this._publisherMap = /* @__PURE__ */ new Map();
516
+ this._webClientMap = /* @__PURE__ */ new Map();
517
+ this._tmpSubscriberShelter = /* @__PURE__ */ new Map();
518
+ this._scheduleJob = null;
519
+ this._setSchedule();
520
+ this._startWsServer();
521
+ this._stopWhenSIGTERMOrSIGINT();
522
+ this._handleUnexpectedExit();
523
+ }
524
+ get hasPublishers() {
525
+ return Boolean(this._publisherMap.size);
526
+ }
527
+ async _startWsServer() {
528
+ const wsHandler = (ws, req) => {
529
+ const { url: reqUrl = "" } = req;
530
+ const { query } = (0, import_url.parse)(reqUrl, true);
531
+ const { WEB_SOCKET_CONNECT_MAGIC_ID: WEB_SOCKET_CONNECT_MAGIC_ID2 } = query;
532
+ if (WEB_SOCKET_CONNECT_MAGIC_ID2 === _Broker.WEB_SOCKET_CONNECT_MAGIC_ID) {
533
+ ws.on("message", (message) => {
534
+ try {
535
+ const text = message.toString();
536
+ const action = JSON.parse(text);
537
+ fileLog(`${action == null ? void 0 : action.kind} action received `, "Broker", "info");
538
+ this._takeAction(action, ws);
539
+ } catch (error2) {
540
+ fileLog(`parse action message error: ${error2}`, "Broker", "error");
541
+ }
542
+ });
543
+ ws.on("error", (e) => {
544
+ fileLog(`parse action message error: ${e}`, "Broker", "error");
545
+ });
546
+ } else {
547
+ ws.send("Invalid CONNECT ID.");
548
+ fileLog("Invalid CONNECT ID.", "Broker", "warn");
549
+ ws.close();
807
550
  }
808
- try {
809
- if (error2) {
810
- await sendMessage({
811
- type: "mf_reject" /* REJECT */,
812
- id: message.id,
813
- error: error2
814
- });
815
- } else {
816
- await sendMessage({
817
- type: "mf_resolve" /* RESOLVE */,
818
- id: message.id,
819
- value
551
+ };
552
+ const server = (0, import_http.createServer)();
553
+ this._webSocketServer = new import_isomorphic_ws.default.Server({ noServer: true });
554
+ this._webSocketServer.on("error", (err) => {
555
+ fileLog(`ws error:
556
+ ${err.message}
557
+ ${err.stack}`, "Broker", "error");
558
+ });
559
+ this._webSocketServer.on("listening", () => {
560
+ fileLog(
561
+ `WebSocket server is listening on port ${_Broker.DEFAULT_WEB_SOCKET_PORT}`,
562
+ "Broker",
563
+ "info"
564
+ );
565
+ });
566
+ this._webSocketServer.on("connection", wsHandler);
567
+ this._webSocketServer.on("close", (code) => {
568
+ fileLog(`WebSocket Server Close with Code ${code}`, "Broker", "warn");
569
+ this._webSocketServer && this._webSocketServer.close();
570
+ this._webSocketServer = void 0;
571
+ });
572
+ server.on("upgrade", (req, socket, head) => {
573
+ var _a;
574
+ if (req.url) {
575
+ const { pathname } = (0, import_url.parse)(req.url);
576
+ if (pathname === "/") {
577
+ (_a = this._webSocketServer) == null ? void 0 : _a.handleUpgrade(req, socket, head, (ws) => {
578
+ var _a2;
579
+ (_a2 = this._webSocketServer) == null ? void 0 : _a2.emit("connection", ws, req);
820
580
  });
821
581
  }
822
- } catch (sendError) {
823
- if (error2) {
824
- if (error2 instanceof Error) {
825
- console.error(error2);
826
- }
827
- }
828
- console.error(sendError);
829
582
  }
830
- }
831
- };
832
- import_process.default.on("message", handleMessage);
833
- }
834
-
835
- // packages/dts-plugin/src/core/rpc/rpc-error.ts
836
- var RpcExitError = class extends Error {
837
- constructor(message, code, signal) {
838
- super(message);
839
- this.code = code;
840
- this.signal = signal;
841
- this.name = "RpcExitError";
583
+ });
584
+ server.listen(_Broker.DEFAULT_WEB_SOCKET_PORT);
842
585
  }
843
- };
844
-
845
- // packages/dts-plugin/src/core/rpc/wrap-rpc.ts
846
- function createControlledPromise() {
847
- let resolve4 = () => void 0;
848
- let reject = () => void 0;
849
- const promise = new Promise((aResolve, aReject) => {
850
- resolve4 = aResolve;
851
- reject = aReject;
852
- });
853
- return {
854
- promise,
855
- resolve: resolve4,
856
- reject
857
- };
858
- }
859
- function wrapRpc(childProcess, options) {
860
- return async (...args) => {
861
- if (!childProcess.send) {
862
- throw new Error(`Process ${childProcess.pid} doesn't have IPC channels`);
863
- } else if (!childProcess.connected) {
864
- throw new Error(
865
- `Process ${childProcess.pid} doesn't have open IPC channels`
586
+ async _takeAction(action, client) {
587
+ const { kind, payload } = action;
588
+ if (kind === "ADD_PUBLISHER" /* ADD_PUBLISHER */) {
589
+ await this._addPublisher(payload, client);
590
+ }
591
+ if (kind === "UPDATE_PUBLISHER" /* UPDATE_PUBLISHER */) {
592
+ await this._updatePublisher(
593
+ payload,
594
+ client
866
595
  );
867
596
  }
868
- const { id, once } = options;
869
- const {
870
- promise: resultPromise,
871
- resolve: resolveResult,
872
- reject: rejectResult
873
- } = createControlledPromise();
874
- const {
875
- promise: sendPromise,
876
- resolve: resolveSend,
877
- reject: rejectSend
878
- } = createControlledPromise();
879
- const handleMessage = (message) => {
880
- if ((message == null ? void 0 : message.id) === id) {
881
- if (message.type === "mf_resolve" /* RESOLVE */) {
882
- resolveResult(message.value);
883
- } else if (message.type === "mf_reject" /* REJECT */) {
884
- rejectResult(message.error);
885
- }
886
- }
887
- if (once && (childProcess == null ? void 0 : childProcess.kill)) {
888
- childProcess.kill("SIGTERM");
889
- }
890
- };
891
- const handleClose = (code, signal) => {
892
- rejectResult(
893
- new RpcExitError(
894
- code ? `Process ${childProcess.pid} exited with code ${code}${signal ? ` [${signal}]` : ""}` : `Process ${childProcess.pid} exited${signal ? ` [${signal}]` : ""}`,
895
- code,
896
- signal
897
- )
597
+ if (kind === "ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */) {
598
+ await this._addSubscriber(payload, client);
599
+ }
600
+ if (kind === "EXIT_SUBSCRIBER" /* EXIT_SUBSCRIBER */) {
601
+ await this._removeSubscriber(
602
+ payload,
603
+ client
898
604
  );
899
- removeHandlers();
900
- };
901
- const removeHandlers = () => {
902
- childProcess.off("message", handleMessage);
903
- childProcess.off("close", handleClose);
904
- };
905
- if (once) {
906
- childProcess.once("message", handleMessage);
907
- } else {
908
- childProcess.on("message", handleMessage);
909
605
  }
910
- childProcess.on("close", handleClose);
911
- childProcess.send(
912
- {
913
- type: "mf_call" /* CALL */,
914
- id,
915
- args
916
- },
917
- (error2) => {
918
- if (error2) {
919
- rejectSend(error2);
920
- removeHandlers();
921
- } else {
922
- resolveSend(void 0);
923
- }
606
+ if (kind === "EXIT_PUBLISHER" /* EXIT_PUBLISHER */) {
607
+ await this._removePublisher(payload, client);
608
+ }
609
+ if (kind === "ADD_WEB_CLIENT" /* ADD_WEB_CLIENT */) {
610
+ await this._addWebClient(payload, client);
611
+ }
612
+ if (kind === "NOTIFY_WEB_CLIENT" /* NOTIFY_WEB_CLIENT */) {
613
+ await this._notifyWebClient(
614
+ payload,
615
+ client
616
+ );
617
+ }
618
+ }
619
+ async _addPublisher(context, client) {
620
+ const { name, ip, remoteTypeTarPath } = context ?? {};
621
+ const identifier = getIdentifier({ name, ip });
622
+ if (this._publisherMap.has(identifier)) {
623
+ fileLog(
624
+ `[${"ADD_PUBLISHER" /* ADD_PUBLISHER */}] ${identifier} has been added, this action will be ignored`,
625
+ "Broker",
626
+ "warn"
627
+ );
628
+ return;
629
+ }
630
+ try {
631
+ const publisher = new Publisher({ name, ip, remoteTypeTarPath });
632
+ this._publisherMap.set(identifier, publisher);
633
+ fileLog(
634
+ `[${"ADD_PUBLISHER" /* ADD_PUBLISHER */}] ${identifier} Adding Publisher Succeed`,
635
+ "Broker",
636
+ "info"
637
+ );
638
+ const tmpSubScribers = this._getTmpSubScribers(identifier);
639
+ if (tmpSubScribers) {
640
+ fileLog(
641
+ `[${"ADD_PUBLISHER" /* ADD_PUBLISHER */}] consumeTmpSubscriber set ${publisher.name}\u2019s subscribers `,
642
+ "Broker",
643
+ "info"
644
+ );
645
+ this._consumeTmpSubScribers(publisher, tmpSubScribers);
646
+ this._clearTmpSubScriberRelation(identifier);
924
647
  }
925
- );
926
- return sendPromise.then(() => resultPromise);
927
- };
928
- }
929
-
930
- // packages/dts-plugin/src/core/rpc/rpc-worker.ts
931
- var child_process = __toESM(require("child_process"));
932
- var process3 = __toESM(require("process"));
933
- var import_crypto = require("crypto");
934
- var FEDERATION_WORKER_DATA_ENV_KEY = "VMOK_WORKER_DATA_ENV";
935
- function createRpcWorker(modulePath, data, memoryLimit, once) {
936
- const options = {
937
- env: {
938
- ...process3.env,
939
- [FEDERATION_WORKER_DATA_ENV_KEY]: JSON.stringify(data || {})
940
- },
941
- stdio: ["inherit", "inherit", "inherit", "ipc"],
942
- serialization: "advanced"
943
- };
944
- if (memoryLimit) {
945
- options.execArgv = [`--max-old-space-size=${memoryLimit}`];
648
+ } catch (err) {
649
+ const msg = error(err, "ADD_PUBLISHER" /* ADD_PUBLISHER */, "Broker");
650
+ client.send(msg);
651
+ client.close();
652
+ }
946
653
  }
947
- let childProcess, remoteMethod;
948
- const id = (0, import_crypto.randomUUID)();
949
- const worker = {
950
- connect(...args) {
951
- if (childProcess && !childProcess.connected) {
952
- childProcess.send({
953
- type: "mf_exit" /* EXIT */,
954
- id
654
+ async _updatePublisher(context, client) {
655
+ const {
656
+ name,
657
+ updateMode,
658
+ updateKind,
659
+ updateSourcePaths,
660
+ remoteTypeTarPath,
661
+ ip
662
+ } = context ?? {};
663
+ const identifier = getIdentifier({ name, ip });
664
+ if (!this._publisherMap.has(identifier)) {
665
+ fileLog(
666
+ `[${"UPDATE_PUBLISHER" /* UPDATE_PUBLISHER */}] ${identifier} has not been started, this action will be ignored
667
+ this._publisherMap: ${JSON.stringify(this._publisherMap.entries())}
668
+ `,
669
+ "Broker",
670
+ "warn"
671
+ );
672
+ return;
673
+ }
674
+ try {
675
+ const publisher = this._publisherMap.get(identifier);
676
+ fileLog(
677
+ // eslint-disable-next-line max-len
678
+ `[${"UPDATE_PUBLISHER" /* UPDATE_PUBLISHER */}] ${identifier} update, and notify subscribers to update`,
679
+ "Broker",
680
+ "info"
681
+ );
682
+ if (publisher) {
683
+ publisher.notifySubscribers({
684
+ remoteTypeTarPath,
685
+ name,
686
+ updateMode,
687
+ updateKind,
688
+ updateSourcePaths: updateSourcePaths || []
955
689
  });
956
- childProcess = void 0;
957
- remoteMethod = void 0;
958
- }
959
- if (!(childProcess == null ? void 0 : childProcess.connected)) {
960
- childProcess = child_process.fork(modulePath, options);
961
- remoteMethod = wrapRpc(childProcess, { id, once });
962
690
  }
963
- if (!remoteMethod) {
964
- return Promise.reject(
965
- new Error("Worker is not connected - cannot perform RPC.")
691
+ } catch (err) {
692
+ const msg = error(err, "UPDATE_PUBLISHER" /* UPDATE_PUBLISHER */, "Broker");
693
+ client.send(msg);
694
+ client.close();
695
+ }
696
+ }
697
+ // app1 consumes provider1,provider2. Dependencies at this time: publishers: [provider1, provider2], subscriberName: app1
698
+ // provider1 is app1's remote
699
+ async _addSubscriber(context, client) {
700
+ const { publishers, name: subscriberName } = context ?? {};
701
+ publishers.forEach((publisher) => {
702
+ const { name, ip } = publisher;
703
+ const identifier = getIdentifier({ name, ip });
704
+ if (!this._publisherMap.has(identifier)) {
705
+ fileLog(
706
+ `[${"ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */}]: ${identifier} has not been started, ${subscriberName} will add the relation to tmp shelter`,
707
+ "Broker",
708
+ "warn"
709
+ );
710
+ this._addTmpSubScriberRelation(
711
+ {
712
+ name: getIdentifier({
713
+ name: context.name,
714
+ ip: context.ip
715
+ }),
716
+ client
717
+ },
718
+ publisher
966
719
  );
720
+ return;
967
721
  }
968
- return remoteMethod(...args);
969
- },
970
- terminate() {
971
- var _a;
972
- (_a = childProcess == null ? void 0 : childProcess.send) == null ? void 0 : _a.call(childProcess, {
973
- type: "mf_exit" /* EXIT */,
974
- id
722
+ try {
723
+ const registeredPublisher = this._publisherMap.get(identifier);
724
+ if (registeredPublisher) {
725
+ registeredPublisher.addSubscriber(
726
+ getIdentifier({
727
+ name: subscriberName,
728
+ ip: context.ip
729
+ }),
730
+ client
731
+ );
732
+ fileLog(
733
+ // eslint-disable-next-line @ies/eden/max-calls-in-template
734
+ `[${"ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */}]: ${identifier} has been started, Adding Subscriber ${subscriberName} Succeed, this.__publisherMap are: ${JSON.stringify(
735
+ Array.from(this._publisherMap.entries())
736
+ )}`,
737
+ "Broker",
738
+ "info"
739
+ );
740
+ registeredPublisher.notifySubscriber(
741
+ getIdentifier({
742
+ name: subscriberName,
743
+ ip: context.ip
744
+ }),
745
+ {
746
+ updateKind: "UPDATE_TYPE" /* UPDATE_TYPE */,
747
+ updateMode: "PASSIVE" /* PASSIVE */,
748
+ updateSourcePaths: [registeredPublisher.name],
749
+ remoteTypeTarPath: registeredPublisher.remoteTypeTarPath,
750
+ name: registeredPublisher.name
751
+ }
752
+ );
753
+ fileLog(
754
+ // eslint-disable-next-line @ies/eden/max-calls-in-template
755
+ `[${"ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */}]: notifySubscriber Subscriber ${subscriberName}, updateMode: "PASSIVE", updateSourcePaths: ${registeredPublisher.name}`,
756
+ "Broker",
757
+ "info"
758
+ );
759
+ }
760
+ } catch (err) {
761
+ const msg = error(err, "ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */, "Broker");
762
+ client.send(msg);
763
+ client.close();
764
+ }
765
+ });
766
+ }
767
+ // Trigger while consumer exit
768
+ async _removeSubscriber(context, client) {
769
+ const { publishers } = context ?? {};
770
+ const subscriberIdentifier = getIdentifier({
771
+ name: context == null ? void 0 : context.name,
772
+ ip: context == null ? void 0 : context.ip
773
+ });
774
+ publishers.forEach((publisher) => {
775
+ const { name, ip } = publisher;
776
+ const identifier = getIdentifier({
777
+ name,
778
+ ip
975
779
  });
976
- childProcess = void 0;
977
- remoteMethod = void 0;
978
- },
979
- get connected() {
980
- return Boolean(childProcess == null ? void 0 : childProcess.connected);
981
- },
982
- get process() {
983
- return childProcess;
984
- },
985
- get id() {
986
- return id;
987
- }
988
- };
989
- return worker;
990
- }
991
- function getRpcWorkerData() {
992
- return JSON.parse(process3.env[FEDERATION_WORKER_DATA_ENV_KEY] || "{}");
993
- }
994
-
995
- // packages/dts-plugin/src/dev-worker/forkDevWorker.ts
996
- var import_sdk5 = require("@module-federation/sdk");
997
-
998
- // packages/dts-plugin/src/server/message/Message.ts
999
- var Message = class {
1000
- constructor(type, kind) {
1001
- this.type = type;
1002
- this.kind = kind;
1003
- this.time = Date.now();
1004
- }
1005
- };
1006
-
1007
- // packages/dts-plugin/src/server/message/API/API.ts
1008
- var API = class extends Message {
1009
- constructor(content, kind) {
1010
- super("API", kind);
1011
- const { code, payload } = content;
1012
- this.code = code;
1013
- this.payload = payload;
1014
- }
1015
- };
1016
-
1017
- // packages/dts-plugin/src/server/message/API/UpdateSubscriber.ts
1018
- var UpdateSubscriberAPI = class extends API {
1019
- constructor(payload) {
1020
- super(
1021
- {
1022
- code: 0,
1023
- payload
1024
- },
1025
- "UPDATE_SUBSCRIBER" /* UPDATE_SUBSCRIBER */
1026
- );
1027
- }
1028
- };
1029
-
1030
- // packages/dts-plugin/src/server/message/API/ReloadWebClient.ts
1031
- var ReloadWebClientAPI = class extends API {
1032
- constructor(payload) {
1033
- super(
1034
- {
1035
- code: 0,
1036
- payload
1037
- },
1038
- "RELOAD_WEB_CLIENT" /* RELOAD_WEB_CLIENT */
1039
- );
1040
- }
1041
- };
1042
-
1043
- // packages/dts-plugin/src/server/utils/index.ts
1044
- var import_net = __toESM(require("net"));
1045
- var import_sdk4 = require("@module-federation/sdk");
1046
-
1047
- // packages/dts-plugin/src/server/utils/logTransform.ts
1048
- var import_chalk = __toESM(require("chalk"));
1049
-
1050
- // packages/dts-plugin/src/server/message/Log/Log.ts
1051
- var Log = class extends Message {
1052
- constructor(level, kind, ignoreVerbose = false) {
1053
- super("Log", kind);
1054
- this.ignoreVerbose = false;
1055
- this.level = level;
1056
- this.ignoreVerbose = ignoreVerbose;
1057
- }
1058
- };
1059
-
1060
- // packages/dts-plugin/src/server/message/Log/BrokerExitLog.ts
1061
- var BrokerExitLog = class extends Log {
1062
- constructor() {
1063
- super("LOG" /* LOG */, "BrokerExitLog" /* BrokerExitLog */);
1064
- }
1065
- };
1066
-
1067
- // packages/dts-plugin/src/server/utils/log.ts
1068
- var import_sdk3 = require("@module-federation/sdk");
1069
- var log4js = __toESM(require("log4js"));
1070
- var import_chalk2 = __toESM(require("chalk"));
1071
-
1072
- // packages/dts-plugin/src/server/constant.ts
1073
- var DEFAULT_WEB_SOCKET_PORT = 16322;
1074
- var WEB_SOCKET_CONNECT_MAGIC_ID = "1hpzW-zo2z-o8io-gfmV1-2cb1d82";
1075
- var MF_SERVER_IDENTIFIER = "Module Federation Dev Server";
1076
- var DEFAULT_TAR_NAME = "@mf-types.zip";
1077
-
1078
- // packages/dts-plugin/src/server/utils/log.ts
1079
- function fileLog(msg, module2, level) {
1080
- var _a, _b;
1081
- if (!((_a = process == null ? void 0 : process.env) == null ? void 0 : _a["FEDERATION_DEBUG"])) {
1082
- return;
1083
- }
1084
- log4js.configure({
1085
- appenders: {
1086
- [module2]: { type: "file", filename: ".mf/typesGenerate.log" },
1087
- default: { type: "file", filename: ".mf/typesGenerate.log" }
1088
- },
1089
- categories: {
1090
- [module2]: { appenders: [module2], level: "error" },
1091
- default: { appenders: ["default"], level: "trace" }
1092
- }
1093
- });
1094
- const logger4 = log4js.getLogger(module2);
1095
- logger4.level = "debug";
1096
- (_b = logger4[level]) == null ? void 0 : _b.call(logger4, msg);
1097
- }
1098
- function error(error2, action, from) {
1099
- const err = error2 instanceof Error ? error2 : new Error(`${action} error`);
1100
- fileLog(`[${action}] error: ${err}`, from, "fatal");
1101
- return err.toString();
1102
- }
1103
-
1104
- // packages/dts-plugin/src/server/utils/getIPV4.ts
1105
- var import_os = __toESM(require("os"));
1106
- var localIpv4 = "127.0.0.1";
1107
- var getIpv4Interfaces = () => {
1108
- try {
1109
- const interfaces = import_os.default.networkInterfaces();
1110
- const ipv4Interfaces = [];
1111
- Object.values(interfaces).forEach((detail) => {
1112
- detail == null ? void 0 : detail.forEach((detail2) => {
1113
- const familyV4Value = typeof detail2.family === "string" ? "IPv4" : 4;
1114
- if (detail2.family === familyV4Value && detail2.address !== localIpv4) {
1115
- ipv4Interfaces.push(detail2);
780
+ const registeredPublisher = this._publisherMap.get(identifier);
781
+ if (!registeredPublisher) {
782
+ fileLog(
783
+ `[${"EXIT_SUBSCRIBER" /* EXIT_SUBSCRIBER */}], ${identifier} does not exit `,
784
+ "Broker",
785
+ "warn"
786
+ );
787
+ return;
788
+ }
789
+ try {
790
+ fileLog(
791
+ `[${"EXIT_SUBSCRIBER" /* EXIT_SUBSCRIBER */}], ${identifier} will exit `,
792
+ "Broker",
793
+ "INFO"
794
+ );
795
+ registeredPublisher.removeSubscriber(subscriberIdentifier);
796
+ this._clearTmpSubScriberRelation(identifier);
797
+ if (!registeredPublisher.hasSubscribes) {
798
+ this._publisherMap.delete(identifier);
1116
799
  }
1117
- });
1118
- });
1119
- return ipv4Interfaces;
1120
- } catch (_err) {
1121
- return [];
1122
- }
1123
- };
1124
- var getIPV4 = () => {
1125
- const ipv4Interfaces = getIpv4Interfaces();
1126
- const ipv4Interface = ipv4Interfaces[0] || { address: localIpv4 };
1127
- return ipv4Interface.address;
1128
- };
1129
-
1130
- // packages/dts-plugin/src/server/utils/index.ts
1131
- function getIdentifier(options) {
1132
- const { ip, name } = options;
1133
- return `mf ${import_sdk4.SEPARATOR}${name}${ip ? `${import_sdk4.SEPARATOR}${ip}` : ""}`;
1134
- }
1135
- function fib(n) {
1136
- let i = 2;
1137
- const res = [0, 1, 1];
1138
- while (i <= n) {
1139
- res[i] = res[i - 1] + res[i - 2];
1140
- i++;
1141
- }
1142
- return res[n];
1143
- }
1144
- function getFreePort() {
1145
- return new Promise((resolve4, reject) => {
1146
- const server = import_net.default.createServer();
1147
- server.unref();
1148
- server.on("error", reject);
1149
- server.listen(0, () => {
1150
- const { port } = server.address();
1151
- server.close(() => {
1152
- resolve4(port);
1153
- });
800
+ if (!this.hasPublishers) {
801
+ this.exit();
802
+ }
803
+ } catch (err) {
804
+ const msg = error(err, "EXIT_SUBSCRIBER" /* EXIT_SUBSCRIBER */, "Broker");
805
+ client.send(msg);
806
+ client.close();
807
+ }
1154
808
  });
1155
- });
1156
- }
1157
-
1158
- // packages/dts-plugin/src/server/Publisher.ts
1159
- var Publisher = class {
1160
- constructor(ctx) {
1161
- this._name = ctx.name;
1162
- this._ip = ctx.ip;
1163
- this._remoteTypeTarPath = ctx.remoteTypeTarPath;
1164
- this._subscribers = /* @__PURE__ */ new Map();
1165
809
  }
1166
- get identifier() {
1167
- return getIdentifier({
1168
- name: this._name,
1169
- ip: this._ip
810
+ async _removePublisher(context, client) {
811
+ const { name, ip } = context ?? {};
812
+ const identifier = getIdentifier({
813
+ name,
814
+ ip
1170
815
  });
1171
- }
1172
- get name() {
1173
- return this._name;
1174
- }
1175
- get ip() {
1176
- return this._ip;
1177
- }
1178
- get remoteTypeTarPath() {
1179
- return this._remoteTypeTarPath;
1180
- }
1181
- get hasSubscribes() {
1182
- return Boolean(this._subscribers.size);
1183
- }
1184
- get subscribers() {
1185
- return this._subscribers;
1186
- }
1187
- addSubscriber(identifier, subscriber) {
1188
- fileLog(`${this.name} set subscriber: ${identifier}`, "Publisher", "info");
1189
- this._subscribers.set(identifier, subscriber);
1190
- }
1191
- removeSubscriber(identifier) {
1192
- if (this._subscribers.has(identifier)) {
816
+ const publisher = this._publisherMap.get(identifier);
817
+ if (!publisher) {
1193
818
  fileLog(
1194
- `${this.name} removeSubscriber: ${identifier}`,
1195
- "Publisher",
819
+ `[${"EXIT_PUBLISHER" /* EXIT_PUBLISHER */}]: ${identifier}} has not been added, this action will be ingored`,
820
+ "Broker",
1196
821
  "warn"
1197
822
  );
1198
- this._subscribers.delete(identifier);
1199
- }
1200
- }
1201
- notifySubscriber(subscriberIdentifier, options) {
1202
- const subscriber = this._subscribers.get(subscriberIdentifier);
1203
- if (!subscriber) {
1204
- fileLog(
1205
- `[notifySubscriber] ${this.name} notifySubscriber: ${subscriberIdentifier}, does not exits`,
1206
- "Publisher",
1207
- "error"
1208
- );
1209
823
  return;
1210
824
  }
1211
- const api = new UpdateSubscriberAPI(options);
1212
- subscriber.send(JSON.stringify(api));
1213
- fileLog(
1214
- `[notifySubscriber] ${this.name} notifySubscriber: ${JSON.stringify(
1215
- subscriberIdentifier
1216
- )}, message: ${JSON.stringify(api)}`,
1217
- "Publisher",
1218
- "info"
1219
- );
1220
- }
1221
- notifySubscribers(options) {
1222
- const api = new UpdateSubscriberAPI(options);
1223
- this.broadcast(api);
1224
- }
1225
- broadcast(message) {
1226
- if (this.hasSubscribes) {
1227
- this._subscribers.forEach((subscriber, key) => {
825
+ try {
826
+ const { subscribers } = publisher;
827
+ subscribers.forEach((subscriber, subscriberIdentifier) => {
828
+ this._addTmpSubScriberRelation(
829
+ {
830
+ name: subscriberIdentifier,
831
+ client: subscriber
832
+ },
833
+ { name: publisher.name, ip: publisher.ip }
834
+ );
1228
835
  fileLog(
1229
- `[BroadCast] ${this.name} notifySubscriber: ${key}, PID: ${process.pid}, message: ${JSON.stringify(message)}`,
1230
- "Publisher",
836
+ // eslint-disable-next-line max-len
837
+ `[${"EXIT_PUBLISHER" /* EXIT_PUBLISHER */}]: ${identifier} is removing , subscriber: ${subscriberIdentifier} will be add tmpSubScriberRelation`,
838
+ "Broker",
1231
839
  "info"
1232
840
  );
1233
- subscriber.send(JSON.stringify(message));
1234
841
  });
1235
- } else {
842
+ this._publisherMap.delete(identifier);
1236
843
  fileLog(
1237
- `[BroadCast] ${this.name}'s subscribe is empty`,
1238
- "Publisher",
1239
- "warn"
844
+ `[${"EXIT_PUBLISHER" /* EXIT_PUBLISHER */}]: ${identifier} is removed `,
845
+ "Broker",
846
+ "info"
1240
847
  );
848
+ if (!this.hasPublishers) {
849
+ fileLog(
850
+ `[${"EXIT_PUBLISHER" /* EXIT_PUBLISHER */}]: _publisherMap is empty, all server will exit `,
851
+ "Broker",
852
+ "warn"
853
+ );
854
+ this.exit();
855
+ }
856
+ } catch (err) {
857
+ const msg = error(err, "EXIT_PUBLISHER" /* EXIT_PUBLISHER */, "Broker");
858
+ client.send(msg);
859
+ client.close();
1241
860
  }
1242
861
  }
1243
- close() {
1244
- this._subscribers.forEach((_subscriber, identifier) => {
862
+ async _addWebClient(context, client) {
863
+ const { name } = context ?? {};
864
+ const identifier = getIdentifier({
865
+ name
866
+ });
867
+ if (this._webClientMap.has(identifier)) {
1245
868
  fileLog(
1246
- `[BroadCast] close ${this.name} remove: ${identifier}`,
1247
- "Publisher",
869
+ `${identifier}} has been added, this action will override prev WebClient`,
870
+ "Broker",
1248
871
  "warn"
1249
872
  );
1250
- this.removeSubscriber(identifier);
1251
- });
873
+ }
874
+ try {
875
+ this._webClientMap.set(identifier, client);
876
+ fileLog(`${identifier} adding WebClient Succeed`, "Broker", "info");
877
+ } catch (err) {
878
+ const msg = error(err, "ADD_WEB_CLIENT" /* ADD_WEB_CLIENT */, "Broker");
879
+ client.send(msg);
880
+ client.close();
881
+ }
1252
882
  }
1253
- };
1254
-
1255
- // packages/dts-plugin/src/server/DevServer.ts
1256
- var import_isomorphic_ws2 = __toESM(require("isomorphic-ws"));
1257
-
1258
- // packages/dts-plugin/src/server/broker/Broker.ts
1259
- var import_http = require("http");
1260
- var import_isomorphic_ws = __toESM(require("isomorphic-ws"));
1261
- var import_node_schedule = __toESM(require("node-schedule"));
1262
- var import_url = require("url");
1263
-
1264
- // packages/dts-plugin/src/server/message/Action/Action.ts
1265
- var Action = class extends Message {
1266
- constructor(content, kind) {
1267
- super("Action", kind);
1268
- const { payload } = content;
1269
- this.payload = payload;
883
+ async _notifyWebClient(context, client) {
884
+ const { name, updateMode } = context ?? {};
885
+ const identifier = getIdentifier({
886
+ name
887
+ });
888
+ const webClient = this._webClientMap.get(identifier);
889
+ if (!webClient) {
890
+ fileLog(
891
+ `[${"NOTIFY_WEB_CLIENT" /* NOTIFY_WEB_CLIENT */}] ${identifier} has not been added, this action will be ignored`,
892
+ "Broker",
893
+ "warn"
894
+ );
895
+ return;
896
+ }
897
+ try {
898
+ const api = new ReloadWebClientAPI({ name, updateMode });
899
+ webClient.send(JSON.stringify(api));
900
+ fileLog(
901
+ `[${"NOTIFY_WEB_CLIENT" /* NOTIFY_WEB_CLIENT */}] Notify ${name} WebClient Succeed`,
902
+ "Broker",
903
+ "info"
904
+ );
905
+ } catch (err) {
906
+ const msg = error(err, "NOTIFY_WEB_CLIENT" /* NOTIFY_WEB_CLIENT */, "Broker");
907
+ client.send(msg);
908
+ client.close();
909
+ }
1270
910
  }
1271
- };
1272
-
1273
- // packages/dts-plugin/src/server/message/Action/AddPublisher.ts
1274
- var AddPublisherAction = class extends Action {
1275
- constructor(payload) {
1276
- super(
1277
- {
1278
- payload
1279
- },
1280
- "ADD_PUBLISHER" /* ADD_PUBLISHER */
1281
- );
911
+ // app1 consumes provider1, and provider1 not launch. this._tmpSubscriberShelter at this time: {provider1: Map{subscribers: Map{app1: app1+ip+client'}, timestamp: 'xx'} }
912
+ _addTmpSubScriberRelation(subscriber, publisher) {
913
+ const publisherIdentifier = getIdentifier({
914
+ name: publisher.name,
915
+ ip: publisher.ip
916
+ });
917
+ const subscriberIdentifier = subscriber.name;
918
+ const shelter = this._tmpSubscriberShelter.get(publisherIdentifier);
919
+ if (!shelter) {
920
+ const map = /* @__PURE__ */ new Map();
921
+ map.set(subscriberIdentifier, subscriber);
922
+ this._tmpSubscriberShelter.set(publisherIdentifier, {
923
+ subscribers: map,
924
+ timestamp: Date.now()
925
+ });
926
+ fileLog(
927
+ `[AddTmpSubscriberRelation] ${publisherIdentifier}'s subscriber has ${subscriberIdentifier} `,
928
+ "Broker",
929
+ "info"
930
+ );
931
+ return;
932
+ }
933
+ const tmpSubScriberShelterSubscriber = shelter.subscribers.get(subscriberIdentifier);
934
+ if (tmpSubScriberShelterSubscriber) {
935
+ fileLog(
936
+ `[AddTmpSubscriberRelation] ${publisherIdentifier} and ${subscriberIdentifier} relation has been added`,
937
+ "Broker",
938
+ "warn"
939
+ );
940
+ shelter.subscribers.set(subscriberIdentifier, subscriber);
941
+ shelter.timestamp = Date.now();
942
+ } else {
943
+ fileLog(
944
+ // eslint-disable-next-line max-len
945
+ `AddTmpSubscriberLog ${publisherIdentifier}'s shelter has been added, update shelter.subscribers ${subscriberIdentifier}`,
946
+ "Broker",
947
+ "warn"
948
+ );
949
+ shelter.subscribers.set(subscriberIdentifier, subscriber);
950
+ }
1282
951
  }
1283
- };
1284
-
1285
- // packages/dts-plugin/src/server/message/Action/AddSubscriber.ts
1286
- var AddSubscriberAction = class extends Action {
1287
- constructor(payload) {
1288
- super(
1289
- {
1290
- payload
1291
- },
1292
- "ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */
1293
- );
952
+ _getTmpSubScribers(publisherIdentifier) {
953
+ var _a;
954
+ return (_a = this._tmpSubscriberShelter.get(publisherIdentifier)) == null ? void 0 : _a.subscribers;
1294
955
  }
1295
- };
1296
-
1297
- // packages/dts-plugin/src/server/message/Action/ExitSubscriber.ts
1298
- var ExitSubscriberAction = class extends Action {
1299
- constructor(payload) {
1300
- super(
1301
- {
1302
- payload
1303
- },
1304
- "EXIT_SUBSCRIBER" /* EXIT_SUBSCRIBER */
1305
- );
956
+ // after adding publisher, it will change the temp subscriber to regular subscriber
957
+ _consumeTmpSubScribers(publisher, tmpSubScribers) {
958
+ tmpSubScribers.forEach((tmpSubScriber, identifier) => {
959
+ fileLog(
960
+ `notifyTmpSubScribers ${publisher.name} will be add a subscriber: ${identifier} `,
961
+ "Broker",
962
+ "warn"
963
+ );
964
+ publisher.addSubscriber(identifier, tmpSubScriber.client);
965
+ publisher.notifySubscriber(identifier, {
966
+ updateKind: "UPDATE_TYPE" /* UPDATE_TYPE */,
967
+ updateMode: "PASSIVE" /* PASSIVE */,
968
+ updateSourcePaths: [publisher.name],
969
+ remoteTypeTarPath: publisher.remoteTypeTarPath,
970
+ name: publisher.name
971
+ });
972
+ });
1306
973
  }
1307
- };
1308
-
1309
- // packages/dts-plugin/src/server/message/Action/ExitPublisher.ts
1310
- var ExitPublisherAction = class extends Action {
1311
- constructor(payload) {
1312
- super(
1313
- {
1314
- payload
1315
- },
1316
- "EXIT_PUBLISHER" /* EXIT_PUBLISHER */
1317
- );
974
+ _clearTmpSubScriberRelation(identifier) {
975
+ this._tmpSubscriberShelter.delete(identifier);
1318
976
  }
1319
- };
1320
-
1321
- // packages/dts-plugin/src/server/message/Action/NotifyWebClient.ts
1322
- var NotifyWebClientAction = class extends Action {
1323
- constructor(payload) {
1324
- super(
1325
- {
1326
- payload
1327
- },
1328
- "NOTIFY_WEB_CLIENT" /* NOTIFY_WEB_CLIENT */
1329
- );
977
+ _clearTmpSubScriberRelations() {
978
+ this._tmpSubscriberShelter.clear();
1330
979
  }
1331
- };
1332
-
1333
- // packages/dts-plugin/src/server/message/Action/UpdatePublisher.ts
1334
- var UpdatePublisherAction = class extends Action {
1335
- constructor(payload) {
1336
- super(
1337
- {
1338
- payload
1339
- },
1340
- "UPDATE_PUBLISHER" /* UPDATE_PUBLISHER */
1341
- );
980
+ _disconnect() {
981
+ this._publisherMap.forEach((publisher) => {
982
+ publisher.close();
983
+ });
1342
984
  }
1343
- };
1344
-
1345
- // packages/dts-plugin/src/server/broker/Broker.ts
1346
- var _Broker = class _Broker {
1347
- constructor() {
1348
- // 1.5h
1349
- this._publisherMap = /* @__PURE__ */ new Map();
1350
- this._webClientMap = /* @__PURE__ */ new Map();
1351
- this._tmpSubscriberShelter = /* @__PURE__ */ new Map();
985
+ // Every day on 0/6/9/12/15//18, Publishers that have not been connected within 1.5 hours will be cleared regularly.
986
+ // If process.env.FEDERATION_SERVER_TEST is set, it will be read at a specified time.
987
+ _setSchedule() {
988
+ const rule = new import_node_schedule.default.RecurrenceRule();
989
+ if (Number(process.env["FEDERATION_SERVER_TEST"])) {
990
+ const interval = Number(process.env["FEDERATION_SERVER_TEST"]) / 1e3;
991
+ const second = [];
992
+ for (let i = 0; i < 60; i = i + interval) {
993
+ second.push(i);
994
+ }
995
+ rule.second = second;
996
+ } else {
997
+ rule.second = 0;
998
+ rule.hour = [0, 3, 6, 9, 12, 15, 18];
999
+ rule.minute = 0;
1000
+ }
1001
+ const serverTest = Number(process.env["FEDERATION_SERVER_TEST"]);
1002
+ this._scheduleJob = import_node_schedule.default.scheduleJob(rule, () => {
1003
+ this._tmpSubscriberShelter.forEach((tmpSubscriber, identifier) => {
1004
+ fileLog(
1005
+ ` _clearTmpSubScriberRelation ${identifier}, ${Date.now() - tmpSubscriber.timestamp >= (process.env["GARFISH_MODULE_SERVER_TEST"] ? serverTest : _Broker.DEFAULT_WAITING_TIME)}`,
1006
+ "Broker",
1007
+ "info"
1008
+ );
1009
+ if (Date.now() - tmpSubscriber.timestamp >= (process.env["FEDERATION_SERVER_TEST"] ? serverTest : _Broker.DEFAULT_WAITING_TIME)) {
1010
+ this._clearTmpSubScriberRelation(identifier);
1011
+ }
1012
+ });
1013
+ });
1014
+ }
1015
+ _clearSchedule() {
1016
+ if (!this._scheduleJob) {
1017
+ return;
1018
+ }
1019
+ this._scheduleJob.cancel();
1352
1020
  this._scheduleJob = null;
1353
- this._setSchedule();
1354
- this._startWsServer();
1355
- this._stopWhenSIGTERMOrSIGINT();
1356
- this._handleUnexpectedExit();
1357
1021
  }
1358
- get hasPublishers() {
1359
- return Boolean(this._publisherMap.size);
1022
+ _stopWhenSIGTERMOrSIGINT() {
1023
+ process.on("SIGTERM", () => {
1024
+ this.exit();
1025
+ });
1026
+ process.on("SIGINT", () => {
1027
+ this.exit();
1028
+ });
1360
1029
  }
1361
- async _startWsServer() {
1362
- const wsHandler = (ws, req) => {
1363
- const { url: reqUrl = "" } = req;
1364
- const { query } = (0, import_url.parse)(reqUrl, true);
1365
- const { WEB_SOCKET_CONNECT_MAGIC_ID: WEB_SOCKET_CONNECT_MAGIC_ID2 } = query;
1366
- if (WEB_SOCKET_CONNECT_MAGIC_ID2 === _Broker.WEB_SOCKET_CONNECT_MAGIC_ID) {
1367
- ws.on("message", (message) => {
1368
- try {
1369
- const text = message.toString();
1370
- const action = JSON.parse(text);
1371
- fileLog(`${action == null ? void 0 : action.kind} action received `, "Broker", "info");
1372
- this._takeAction(action, ws);
1373
- } catch (error2) {
1374
- fileLog(`parse action message error: ${error2}`, "Broker", "error");
1375
- }
1376
- });
1377
- ws.on("error", (e) => {
1378
- fileLog(`parse action message error: ${e}`, "Broker", "error");
1379
- });
1380
- } else {
1381
- ws.send("Invalid CONNECT ID.");
1382
- fileLog("Invalid CONNECT ID.", "Broker", "warn");
1383
- ws.close();
1384
- }
1385
- };
1386
- const server = (0, import_http.createServer)();
1387
- this._webSocketServer = new import_isomorphic_ws.default.Server({ noServer: true });
1388
- this._webSocketServer.on("error", (err) => {
1389
- fileLog(`ws error:
1390
- ${err.message}
1391
- ${err.stack}`, "Broker", "error");
1030
+ _handleUnexpectedExit() {
1031
+ process.on("unhandledRejection", (error2) => {
1032
+ console.error("Unhandled Rejection Error: ", error2);
1033
+ fileLog(`Unhandled Rejection Error: ${error2}`, "Broker", "fatal");
1034
+ process.exit(1);
1392
1035
  });
1393
- this._webSocketServer.on("listening", () => {
1394
- fileLog(
1395
- `WebSocket server is listening on port ${_Broker.DEFAULT_WEB_SOCKET_PORT}`,
1396
- "Broker",
1397
- "info"
1398
- );
1036
+ process.on("uncaughtException", (error2) => {
1037
+ console.error("Unhandled Exception Error: ", error2);
1038
+ fileLog(`Unhandled Rejection Error: ${error2}`, "Broker", "fatal");
1039
+ process.exit(1);
1399
1040
  });
1400
- this._webSocketServer.on("connection", wsHandler);
1401
- this._webSocketServer.on("close", (code) => {
1402
- fileLog(`WebSocket Server Close with Code ${code}`, "Broker", "warn");
1403
- this._webSocketServer && this._webSocketServer.close();
1404
- this._webSocketServer = void 0;
1041
+ }
1042
+ async start() {
1043
+ }
1044
+ exit() {
1045
+ const brokerExitLog = new BrokerExitLog();
1046
+ this.broadcast(JSON.stringify(brokerExitLog));
1047
+ this._disconnect();
1048
+ this._clearSchedule();
1049
+ this._clearTmpSubScriberRelations();
1050
+ this._webSocketServer && this._webSocketServer.close();
1051
+ this._secureWebSocketServer && this._secureWebSocketServer.close();
1052
+ process.exit(0);
1053
+ }
1054
+ broadcast(message) {
1055
+ var _a, _b;
1056
+ fileLog(
1057
+ `[broadcast] exit info : ${JSON.stringify(message)}`,
1058
+ "Broker",
1059
+ "warn"
1060
+ );
1061
+ (_a = this._webSocketServer) == null ? void 0 : _a.clients.forEach((client) => {
1062
+ client.send(JSON.stringify(message));
1405
1063
  });
1406
- server.on("upgrade", (req, socket, head) => {
1407
- var _a;
1408
- if (req.url) {
1409
- const { pathname } = (0, import_url.parse)(req.url);
1410
- if (pathname === "/") {
1411
- (_a = this._webSocketServer) == null ? void 0 : _a.handleUpgrade(req, socket, head, (ws) => {
1412
- var _a2;
1413
- (_a2 = this._webSocketServer) == null ? void 0 : _a2.emit("connection", ws, req);
1414
- });
1415
- }
1416
- }
1064
+ (_b = this._secureWebSocketServer) == null ? void 0 : _b.clients.forEach((client) => {
1065
+ client.send(JSON.stringify(message));
1417
1066
  });
1418
- server.listen(_Broker.DEFAULT_WEB_SOCKET_PORT);
1419
1067
  }
1420
- async _takeAction(action, client) {
1421
- const { kind, payload } = action;
1422
- if (kind === "ADD_PUBLISHER" /* ADD_PUBLISHER */) {
1423
- await this._addPublisher(payload, client);
1424
- }
1425
- if (kind === "UPDATE_PUBLISHER" /* UPDATE_PUBLISHER */) {
1426
- await this._updatePublisher(
1427
- payload,
1428
- client
1429
- );
1430
- }
1431
- if (kind === "ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */) {
1432
- await this._addSubscriber(payload, client);
1433
- }
1434
- if (kind === "EXIT_SUBSCRIBER" /* EXIT_SUBSCRIBER */) {
1435
- await this._removeSubscriber(
1436
- payload,
1437
- client
1438
- );
1439
- }
1440
- if (kind === "EXIT_PUBLISHER" /* EXIT_PUBLISHER */) {
1441
- await this._removePublisher(payload, client);
1442
- }
1443
- if (kind === "ADD_WEB_CLIENT" /* ADD_WEB_CLIENT */) {
1444
- await this._addWebClient(payload, client);
1445
- }
1446
- if (kind === "NOTIFY_WEB_CLIENT" /* NOTIFY_WEB_CLIENT */) {
1447
- await this._notifyWebClient(
1448
- payload,
1449
- client
1450
- );
1451
- }
1068
+ };
1069
+ _Broker.WEB_SOCKET_CONNECT_MAGIC_ID = WEB_SOCKET_CONNECT_MAGIC_ID;
1070
+ _Broker.DEFAULT_WEB_SOCKET_PORT = DEFAULT_WEB_SOCKET_PORT;
1071
+ _Broker.DEFAULT_SECURE_WEB_SOCKET_PORT = 16324;
1072
+ _Broker.DEFAULT_WAITING_TIME = 1.5 * 60 * 60 * 1e3;
1073
+ var Broker = _Broker;
1074
+
1075
+ // packages/dts-plugin/src/server/broker/createBroker.ts
1076
+ var import_child_process = require("child_process");
1077
+ var import_path2 = __toESM(require("path"));
1078
+ function createBroker() {
1079
+ const startBrokerPath = import_path2.default.resolve(__dirname, "./startBroker.js");
1080
+ const sub = (0, import_child_process.fork)(startBrokerPath, [], {
1081
+ detached: true,
1082
+ stdio: "ignore",
1083
+ env: process.env
1084
+ });
1085
+ sub.send("start");
1086
+ sub.unref();
1087
+ return sub;
1088
+ }
1089
+
1090
+ // packages/dts-plugin/src/server/DevServer.ts
1091
+ var ModuleFederationDevServer = class {
1092
+ constructor(ctx) {
1093
+ this._publishWebSocket = null;
1094
+ this._subscriberWebsocketMap = {};
1095
+ this._reconnect = true;
1096
+ this._reconnectTimes = 0;
1097
+ this._isConnected = false;
1098
+ this._isReconnecting = false;
1099
+ this._updateCallback = () => Promise.resolve(void 0);
1100
+ const { name, remotes, remoteTypeTarPath, updateCallback: updateCallback2 } = ctx;
1101
+ this._ip = getIPV4();
1102
+ this._name = name;
1103
+ this._remotes = remotes;
1104
+ this._remoteTypeTarPath = remoteTypeTarPath;
1105
+ this._updateCallback = updateCallback2;
1106
+ this._stopWhenSIGTERMOrSIGINT();
1107
+ this._handleUnexpectedExit();
1108
+ this._connectPublishToServer();
1452
1109
  }
1453
- async _addPublisher(context, client) {
1454
- const { name, ip, remoteTypeTarPath } = context ?? {};
1455
- const identifier = getIdentifier({ name, ip });
1456
- if (this._publisherMap.has(identifier)) {
1457
- fileLog(
1458
- `[${"ADD_PUBLISHER" /* ADD_PUBLISHER */}] ${identifier} has been added, this action will be ignored`,
1459
- "Broker",
1460
- "warn"
1461
- );
1110
+ _connectPublishToServer() {
1111
+ if (!this._reconnect) {
1462
1112
  return;
1463
1113
  }
1464
- try {
1465
- const publisher = new Publisher({ name, ip, remoteTypeTarPath });
1466
- this._publisherMap.set(identifier, publisher);
1114
+ fileLog(
1115
+ `Publisher:${this._name} Trying to connect to ws://${this._ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}...`,
1116
+ MF_SERVER_IDENTIFIER,
1117
+ "info"
1118
+ );
1119
+ this._publishWebSocket = new import_isomorphic_ws2.default(
1120
+ `ws://${this._ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}?WEB_SOCKET_CONNECT_MAGIC_ID=${Broker.WEB_SOCKET_CONNECT_MAGIC_ID}`
1121
+ );
1122
+ this._publishWebSocket.on("open", () => {
1123
+ var _a;
1467
1124
  fileLog(
1468
- `[${"ADD_PUBLISHER" /* ADD_PUBLISHER */}] ${identifier} Adding Publisher Succeed`,
1469
- "Broker",
1125
+ `Current pid: ${process.pid}, publisher:${this._name} connected to ws://${this._ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}, starting service...`,
1126
+ MF_SERVER_IDENTIFIER,
1470
1127
  "info"
1471
1128
  );
1472
- const tmpSubScribers = this._getTmpSubScribers(identifier);
1473
- if (tmpSubScribers) {
1474
- fileLog(
1475
- `[${"ADD_PUBLISHER" /* ADD_PUBLISHER */}] consumeTmpSubscriber set ${publisher.name}\u2019s subscribers `,
1476
- "Broker",
1477
- "info"
1129
+ this._isConnected = true;
1130
+ const startGarfishModule = new AddPublisherAction({
1131
+ name: this._name,
1132
+ ip: this._ip,
1133
+ remoteTypeTarPath: this._remoteTypeTarPath
1134
+ });
1135
+ (_a = this._publishWebSocket) == null ? void 0 : _a.send(JSON.stringify(startGarfishModule));
1136
+ this._connectSubscribers();
1137
+ });
1138
+ this._publishWebSocket.on("message", (message) => {
1139
+ var _a, _b;
1140
+ try {
1141
+ const parsedMessage = JSON.parse(
1142
+ message.toString()
1478
1143
  );
1479
- this._consumeTmpSubScribers(publisher, tmpSubScribers);
1480
- this._clearTmpSubScriberRelation(identifier);
1481
- }
1482
- } catch (err) {
1483
- const msg = error(err, "ADD_PUBLISHER" /* ADD_PUBLISHER */, "Broker");
1484
- client.send(msg);
1485
- client.close();
1486
- }
1487
- }
1488
- async _updatePublisher(context, client) {
1489
- const {
1490
- name,
1491
- updateMode,
1492
- updateKind,
1493
- updateSourcePaths,
1494
- remoteTypeTarPath,
1495
- ip
1496
- } = context ?? {};
1497
- const identifier = getIdentifier({ name, ip });
1498
- if (!this._publisherMap.has(identifier)) {
1499
- fileLog(
1500
- `[${"UPDATE_PUBLISHER" /* UPDATE_PUBLISHER */}] ${identifier} has not been started, this action will be ignored
1501
- this._publisherMap: ${JSON.stringify(this._publisherMap.entries())}
1502
- `,
1503
- "Broker",
1504
- "warn"
1505
- );
1506
- return;
1507
- }
1508
- try {
1509
- const publisher = this._publisherMap.get(identifier);
1510
- fileLog(
1511
- // eslint-disable-next-line max-len
1512
- `[${"UPDATE_PUBLISHER" /* UPDATE_PUBLISHER */}] ${identifier} update, and notify subscribers to update`,
1513
- "Broker",
1514
- "info"
1515
- );
1516
- if (publisher) {
1517
- publisher.notifySubscribers({
1518
- remoteTypeTarPath,
1519
- name,
1520
- updateMode,
1521
- updateKind,
1522
- updateSourcePaths: updateSourcePaths || []
1144
+ if (parsedMessage.type === "Log") {
1145
+ if (parsedMessage.kind === "BrokerExitLog" /* BrokerExitLog */) {
1146
+ fileLog(
1147
+ `Receive broker exit signal, ${this._name} service will exit...`,
1148
+ MF_SERVER_IDENTIFIER,
1149
+ "warn"
1150
+ );
1151
+ this._exit();
1152
+ }
1153
+ }
1154
+ } catch (err) {
1155
+ console.error(err);
1156
+ const exitPublisher = new ExitPublisherAction({
1157
+ name: this._name,
1158
+ ip: this._ip
1523
1159
  });
1524
- }
1525
- } catch (err) {
1526
- const msg = error(err, "UPDATE_PUBLISHER" /* UPDATE_PUBLISHER */, "Broker");
1527
- client.send(msg);
1528
- client.close();
1529
- }
1530
- }
1531
- // app1 consumes provider1,provider2. Dependencies at this time: publishers: [provider1, provider2], subscriberName: app1
1532
- // provider1 is app1's remote
1533
- async _addSubscriber(context, client) {
1534
- const { publishers, name: subscriberName } = context ?? {};
1535
- publishers.forEach((publisher) => {
1536
- const { name, ip } = publisher;
1537
- const identifier = getIdentifier({ name, ip });
1538
- if (!this._publisherMap.has(identifier)) {
1160
+ const exitSubscriber = new ExitSubscriberAction({
1161
+ name: this._name,
1162
+ ip: this._ip,
1163
+ publishers: this._remotes.map((remote) => ({
1164
+ name: remote.name,
1165
+ ip: remote.ip
1166
+ }))
1167
+ });
1168
+ (_a = this._publishWebSocket) == null ? void 0 : _a.send(JSON.stringify(exitPublisher));
1169
+ (_b = this._publishWebSocket) == null ? void 0 : _b.send(JSON.stringify(exitSubscriber));
1539
1170
  fileLog(
1540
- `[${"ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */}]: ${identifier} has not been started, ${subscriberName} will add the relation to tmp shelter`,
1541
- "Broker",
1542
- "warn"
1543
- );
1544
- this._addTmpSubScriberRelation(
1545
- {
1546
- name: getIdentifier({
1547
- name: context.name,
1548
- ip: context.ip
1549
- }),
1550
- client
1551
- },
1552
- publisher
1171
+ "Parse messages error, ModuleFederationDevServer will exit...",
1172
+ MF_SERVER_IDENTIFIER,
1173
+ "fatal"
1553
1174
  );
1554
- return;
1555
- }
1556
- try {
1557
- const registeredPublisher = this._publisherMap.get(identifier);
1558
- if (registeredPublisher) {
1559
- registeredPublisher.addSubscriber(
1560
- getIdentifier({
1561
- name: subscriberName,
1562
- ip: context.ip
1563
- }),
1564
- client
1565
- );
1566
- fileLog(
1567
- // eslint-disable-next-line @ies/eden/max-calls-in-template
1568
- `[${"ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */}]: ${identifier} has been started, Adding Subscriber ${subscriberName} Succeed, this.__publisherMap are: ${JSON.stringify(
1569
- Array.from(this._publisherMap.entries())
1570
- )}`,
1571
- "Broker",
1572
- "info"
1573
- );
1574
- registeredPublisher.notifySubscriber(
1575
- getIdentifier({
1576
- name: subscriberName,
1577
- ip: context.ip
1578
- }),
1579
- {
1580
- updateKind: "UPDATE_TYPE" /* UPDATE_TYPE */,
1581
- updateMode: "PASSIVE" /* PASSIVE */,
1582
- updateSourcePaths: [registeredPublisher.name],
1583
- remoteTypeTarPath: registeredPublisher.remoteTypeTarPath,
1584
- name: registeredPublisher.name
1585
- }
1586
- );
1587
- fileLog(
1588
- // eslint-disable-next-line @ies/eden/max-calls-in-template
1589
- `[${"ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */}]: notifySubscriber Subscriber ${subscriberName}, updateMode: "PASSIVE", updateSourcePaths: ${registeredPublisher.name}`,
1590
- "Broker",
1591
- "info"
1592
- );
1593
- }
1594
- } catch (err) {
1595
- const msg = error(err, "ADD_SUBSCRIBER" /* ADD_SUBSCRIBER */, "Broker");
1596
- client.send(msg);
1597
- client.close();
1175
+ this._exit();
1598
1176
  }
1599
1177
  });
1600
- }
1601
- // Trigger while consumer exit
1602
- async _removeSubscriber(context, client) {
1603
- const { publishers } = context ?? {};
1604
- const subscriberIdentifier = getIdentifier({
1605
- name: context == null ? void 0 : context.name,
1606
- ip: context == null ? void 0 : context.ip
1607
- });
1608
- publishers.forEach((publisher) => {
1609
- const { name, ip } = publisher;
1610
- const identifier = getIdentifier({
1611
- name,
1612
- ip
1613
- });
1614
- const registeredPublisher = this._publisherMap.get(identifier);
1615
- if (!registeredPublisher) {
1616
- fileLog(
1617
- `[${"EXIT_SUBSCRIBER" /* EXIT_SUBSCRIBER */}], ${identifier} does not exit `,
1618
- "Broker",
1619
- "warn"
1620
- );
1178
+ this._publishWebSocket.on("close", (code) => {
1179
+ fileLog(
1180
+ `Connection closed with code ${code}.`,
1181
+ MF_SERVER_IDENTIFIER,
1182
+ "warn"
1183
+ );
1184
+ this._publishWebSocket && this._publishWebSocket.close();
1185
+ this._publishWebSocket = null;
1186
+ if (!this._reconnect) {
1621
1187
  return;
1622
1188
  }
1623
- try {
1624
- fileLog(
1625
- `[${"EXIT_SUBSCRIBER" /* EXIT_SUBSCRIBER */}], ${identifier} will exit `,
1626
- "Broker",
1627
- "INFO"
1628
- );
1629
- registeredPublisher.removeSubscriber(subscriberIdentifier);
1630
- this._clearTmpSubScriberRelation(identifier);
1631
- if (!registeredPublisher.hasSubscribes) {
1632
- this._publisherMap.delete(identifier);
1633
- }
1634
- if (!this.hasPublishers) {
1635
- this.exit();
1636
- }
1637
- } catch (err) {
1638
- const msg = error(err, "EXIT_SUBSCRIBER" /* EXIT_SUBSCRIBER */, "Broker");
1639
- client.send(msg);
1640
- client.close();
1641
- }
1189
+ const reconnectTime = fib(++this._reconnectTimes);
1190
+ fileLog(
1191
+ `start reconnecting to server after ${reconnectTime}s.`,
1192
+ MF_SERVER_IDENTIFIER,
1193
+ "info"
1194
+ );
1195
+ setTimeout(() => this._connectPublishToServer(), reconnectTime * 1e3);
1642
1196
  });
1197
+ this._publishWebSocket.on(
1198
+ "error",
1199
+ this._tryCreateBackgroundBroker.bind(this)
1200
+ );
1643
1201
  }
1644
- async _removePublisher(context, client) {
1645
- const { name, ip } = context ?? {};
1202
+ // Associate the remotes(Subscriber) to the Broker
1203
+ _connectSubscriberToServer(remote) {
1204
+ const { name, ip } = remote;
1205
+ fileLog(
1206
+ `remote module:${name} trying to connect to ws://${ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}...`,
1207
+ MF_SERVER_IDENTIFIER,
1208
+ "info"
1209
+ );
1646
1210
  const identifier = getIdentifier({
1647
1211
  name,
1648
1212
  ip
1649
1213
  });
1650
- const publisher = this._publisherMap.get(identifier);
1651
- if (!publisher) {
1214
+ this._subscriberWebsocketMap[identifier] = new import_isomorphic_ws2.default(
1215
+ `ws://${ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}?WEB_SOCKET_CONNECT_MAGIC_ID=${Broker.WEB_SOCKET_CONNECT_MAGIC_ID}`
1216
+ );
1217
+ this._subscriberWebsocketMap[identifier].on("open", () => {
1652
1218
  fileLog(
1653
- `[${"EXIT_PUBLISHER" /* EXIT_PUBLISHER */}]: ${identifier}} has not been added, this action will be ingored`,
1654
- "Broker",
1655
- "warn"
1219
+ `Current pid: ${process.pid} remote module: ${name} connected to ws://${ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}, starting service...`,
1220
+ MF_SERVER_IDENTIFIER,
1221
+ "info"
1656
1222
  );
1657
- return;
1658
- }
1659
- try {
1660
- const { subscribers } = publisher;
1661
- subscribers.forEach((subscriber, subscriberIdentifier) => {
1662
- this._addTmpSubScriberRelation(
1223
+ const addSubscriber = new AddSubscriberAction({
1224
+ name: this._name,
1225
+ // module self name
1226
+ ip: this._ip,
1227
+ publishers: [
1663
1228
  {
1664
- name: subscriberIdentifier,
1665
- client: subscriber
1666
- },
1667
- { name: publisher.name, ip: publisher.ip }
1668
- );
1669
- fileLog(
1670
- // eslint-disable-next-line max-len
1671
- `[${"EXIT_PUBLISHER" /* EXIT_PUBLISHER */}]: ${identifier} is removing , subscriber: ${subscriberIdentifier} will be add tmpSubScriberRelation`,
1672
- "Broker",
1673
- "info"
1674
- );
1229
+ name,
1230
+ // remote's name
1231
+ ip
1232
+ }
1233
+ ]
1675
1234
  });
1676
- this._publisherMap.delete(identifier);
1677
- fileLog(
1678
- `[${"EXIT_PUBLISHER" /* EXIT_PUBLISHER */}]: ${identifier} is removed `,
1679
- "Broker",
1680
- "info"
1235
+ this._subscriberWebsocketMap[identifier].send(
1236
+ JSON.stringify(addSubscriber)
1681
1237
  );
1682
- if (!this.hasPublishers) {
1238
+ });
1239
+ this._subscriberWebsocketMap[identifier].on("message", async (message) => {
1240
+ try {
1241
+ const parsedMessage = JSON.parse(
1242
+ message.toString()
1243
+ );
1244
+ if (parsedMessage.type === "Log") {
1245
+ if (parsedMessage.kind === "BrokerExitLog" /* BrokerExitLog */) {
1246
+ fileLog(
1247
+ `${identifier}'s Server exit, thus ${identifier} will no longer has reload ability.`,
1248
+ MF_SERVER_IDENTIFIER,
1249
+ "warn"
1250
+ );
1251
+ this._exit();
1252
+ }
1253
+ }
1254
+ if (parsedMessage.type === "API") {
1255
+ if (parsedMessage.kind === "UPDATE_SUBSCRIBER" /* UPDATE_SUBSCRIBER */) {
1256
+ const {
1257
+ payload: {
1258
+ updateKind,
1259
+ updateSourcePaths,
1260
+ name: subscribeName,
1261
+ remoteTypeTarPath,
1262
+ updateMode
1263
+ }
1264
+ } = parsedMessage;
1265
+ await this._updateSubscriber({
1266
+ remoteTypeTarPath,
1267
+ name: subscribeName,
1268
+ updateKind,
1269
+ updateMode,
1270
+ updateSourcePaths
1271
+ });
1272
+ }
1273
+ }
1274
+ } catch (err) {
1275
+ console.error(err);
1276
+ const exitSubscriber = new ExitSubscriberAction({
1277
+ name: this._name,
1278
+ ip: this._ip,
1279
+ publishers: [
1280
+ {
1281
+ name,
1282
+ ip
1283
+ }
1284
+ ]
1285
+ });
1286
+ this._subscriberWebsocketMap[identifier].send(
1287
+ JSON.stringify(exitSubscriber)
1288
+ );
1683
1289
  fileLog(
1684
- `[${"EXIT_PUBLISHER" /* EXIT_PUBLISHER */}]: _publisherMap is empty, all server will exit `,
1685
- "Broker",
1290
+ `${identifier} exit,
1291
+ error: ${err instanceof Error ? err.toString() : JSON.stringify(err)}
1292
+ `,
1293
+ MF_SERVER_IDENTIFIER,
1686
1294
  "warn"
1687
1295
  );
1688
- this.exit();
1689
1296
  }
1690
- } catch (err) {
1691
- const msg = error(err, "EXIT_PUBLISHER" /* EXIT_PUBLISHER */, "Broker");
1692
- client.send(msg);
1693
- client.close();
1694
- }
1695
- }
1696
- async _addWebClient(context, client) {
1697
- const { name } = context ?? {};
1698
- const identifier = getIdentifier({
1699
- name
1700
1297
  });
1701
- if (this._webClientMap.has(identifier)) {
1298
+ this._subscriberWebsocketMap[identifier].on("close", (code) => {
1702
1299
  fileLog(
1703
- `${identifier}} has been added, this action will override prev WebClient`,
1704
- "Broker",
1300
+ `Connection closed with code ${code}.`,
1301
+ MF_SERVER_IDENTIFIER,
1705
1302
  "warn"
1706
1303
  );
1707
- }
1708
- try {
1709
- this._webClientMap.set(identifier, client);
1710
- fileLog(`${identifier} adding WebClient Succeed`, "Broker", "info");
1711
- } catch (err) {
1712
- const msg = error(err, "ADD_WEB_CLIENT" /* ADD_WEB_CLIENT */, "Broker");
1713
- client.send(msg);
1714
- client.close();
1715
- }
1304
+ this._subscriberWebsocketMap[identifier] && this._subscriberWebsocketMap[identifier].close();
1305
+ delete this._subscriberWebsocketMap[identifier];
1306
+ });
1716
1307
  }
1717
- async _notifyWebClient(context, client) {
1718
- const { name, updateMode } = context ?? {};
1719
- const identifier = getIdentifier({
1720
- name
1308
+ _connectSubscribers() {
1309
+ this._remotes.forEach((remote) => {
1310
+ this._connectSubscriberToServer(remote);
1721
1311
  });
1722
- const webClient = this._webClientMap.get(identifier);
1723
- if (!webClient) {
1312
+ }
1313
+ // app1 consumes provider1. And the function will be triggered when provider1 code change.
1314
+ async _updateSubscriber(options) {
1315
+ var _a;
1316
+ const {
1317
+ updateMode,
1318
+ updateKind,
1319
+ updateSourcePaths,
1320
+ name,
1321
+ remoteTypeTarPath
1322
+ } = options;
1323
+ if (updateMode === "PASSIVE" /* PASSIVE */ && updateSourcePaths.includes(this._name)) {
1724
1324
  fileLog(
1725
- `[${"NOTIFY_WEB_CLIENT" /* NOTIFY_WEB_CLIENT */}] ${identifier} has not been added, this action will be ignored`,
1726
- "Broker",
1325
+ // eslint-disable-next-line max-len
1326
+ `[_updateSubscriber] run, updateSourcePaths:${updateSourcePaths} includes ${this._name}, update ignore!`,
1327
+ MF_SERVER_IDENTIFIER,
1727
1328
  "warn"
1728
1329
  );
1729
1330
  return;
1730
1331
  }
1731
- try {
1732
- const api = new ReloadWebClientAPI({ name, updateMode });
1733
- webClient.send(JSON.stringify(api));
1332
+ if (updateSourcePaths.slice(-1)[0] === this._name) {
1734
1333
  fileLog(
1735
- `[${"NOTIFY_WEB_CLIENT" /* NOTIFY_WEB_CLIENT */}] Notify ${name} WebClient Succeed`,
1736
- "Broker",
1737
- "info"
1334
+ `[_updateSubscriber] run, updateSourcePaths:${updateSourcePaths} ends is ${this._name}, update ignore!`,
1335
+ MF_SERVER_IDENTIFIER,
1336
+ "warn"
1738
1337
  );
1739
- } catch (err) {
1740
- const msg = error(err, "NOTIFY_WEB_CLIENT" /* NOTIFY_WEB_CLIENT */, "Broker");
1741
- client.send(msg);
1742
- client.close();
1338
+ return;
1743
1339
  }
1744
- }
1745
- // app1 consumes provider1, and provider1 not launch. this._tmpSubscriberShelter at this time: {provider1: Map{subscribers: Map{app1: app1+ip+client'}, timestamp: 'xx'} }
1746
- _addTmpSubScriberRelation(subscriber, publisher) {
1747
- const publisherIdentifier = getIdentifier({
1748
- name: publisher.name,
1749
- ip: publisher.ip
1340
+ fileLog(
1341
+ // eslint-disable-next-line max-len
1342
+ `[_updateSubscriber] run, updateSourcePaths:${updateSourcePaths}, current module:${this._name}, update start...`,
1343
+ MF_SERVER_IDENTIFIER,
1344
+ "info"
1345
+ );
1346
+ await this._updateCallback({
1347
+ name,
1348
+ updateMode,
1349
+ updateKind,
1350
+ updateSourcePaths,
1351
+ remoteTypeTarPath
1750
1352
  });
1751
- const subscriberIdentifier = subscriber.name;
1752
- const shelter = this._tmpSubscriberShelter.get(publisherIdentifier);
1753
- if (!shelter) {
1754
- const map = /* @__PURE__ */ new Map();
1755
- map.set(subscriberIdentifier, subscriber);
1756
- this._tmpSubscriberShelter.set(publisherIdentifier, {
1757
- subscribers: map,
1758
- timestamp: Date.now()
1759
- });
1760
- fileLog(
1761
- `[AddTmpSubscriberRelation] ${publisherIdentifier}'s subscriber has ${subscriberIdentifier} `,
1762
- "Broker",
1763
- "info"
1764
- );
1353
+ const newUpdateSourcePaths = updateSourcePaths.concat(this._name);
1354
+ const updatePublisher = new UpdatePublisherAction({
1355
+ name: this._name,
1356
+ ip: this._ip,
1357
+ updateMode: "PASSIVE" /* PASSIVE */,
1358
+ updateKind,
1359
+ updateSourcePaths: newUpdateSourcePaths,
1360
+ remoteTypeTarPath: this._remoteTypeTarPath
1361
+ });
1362
+ fileLog(
1363
+ // eslint-disable-next-line max-len
1364
+ `[_updateSubscriber] run, updateSourcePaths:${newUpdateSourcePaths}, update publisher ${this._name} start...`,
1365
+ MF_SERVER_IDENTIFIER,
1366
+ "info"
1367
+ );
1368
+ (_a = this._publishWebSocket) == null ? void 0 : _a.send(JSON.stringify(updatePublisher));
1369
+ }
1370
+ _tryCreateBackgroundBroker(err) {
1371
+ if (!((err == null ? void 0 : err.code) === "ECONNREFUSED" && err.port === Broker.DEFAULT_WEB_SOCKET_PORT)) {
1372
+ fileLog(`websocket error: ${err.stack}`, MF_SERVER_IDENTIFIER, "fatal");
1765
1373
  return;
1766
1374
  }
1767
- const tmpSubScriberShelterSubscriber = shelter.subscribers.get(subscriberIdentifier);
1768
- if (tmpSubScriberShelterSubscriber) {
1375
+ fileLog(
1376
+ `Failed to connect to ws://${this._ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}...`,
1377
+ MF_SERVER_IDENTIFIER,
1378
+ "fatal"
1379
+ );
1380
+ this._isReconnecting = true;
1381
+ setTimeout(
1382
+ () => {
1383
+ this._isReconnecting = false;
1384
+ if (this._reconnect === false) {
1385
+ return;
1386
+ }
1387
+ fileLog(
1388
+ "Creating new background broker...",
1389
+ MF_SERVER_IDENTIFIER,
1390
+ "warn"
1391
+ );
1392
+ const broker = createBroker();
1393
+ broker.on("message", (message) => {
1394
+ if (message === "ready") {
1395
+ fileLog("background broker started.", MF_SERVER_IDENTIFIER, "info");
1396
+ this._reconnectTimes = 1;
1397
+ if (process.send) {
1398
+ process.send("ready");
1399
+ }
1400
+ }
1401
+ });
1402
+ },
1403
+ Math.ceil(100 * Math.random())
1404
+ );
1405
+ }
1406
+ _stopWhenSIGTERMOrSIGINT() {
1407
+ process.on("SIGTERM", () => {
1769
1408
  fileLog(
1770
- `[AddTmpSubscriberRelation] ${publisherIdentifier} and ${subscriberIdentifier} relation has been added`,
1771
- "Broker",
1409
+ `Process(${process.pid}) SIGTERM, ModuleFederationDevServer will exit...`,
1410
+ MF_SERVER_IDENTIFIER,
1772
1411
  "warn"
1773
1412
  );
1774
- shelter.subscribers.set(subscriberIdentifier, subscriber);
1775
- shelter.timestamp = Date.now();
1776
- } else {
1413
+ this._exit();
1414
+ });
1415
+ process.on("SIGINT", () => {
1777
1416
  fileLog(
1778
- // eslint-disable-next-line max-len
1779
- `AddTmpSubscriberLog ${publisherIdentifier}'s shelter has been added, update shelter.subscribers ${subscriberIdentifier}`,
1780
- "Broker",
1417
+ `Process(${process.pid}) SIGINT, ModuleFederationDevServer will exit...`,
1418
+ MF_SERVER_IDENTIFIER,
1781
1419
  "warn"
1782
1420
  );
1783
- shelter.subscribers.set(subscriberIdentifier, subscriber);
1784
- }
1785
- }
1786
- _getTmpSubScribers(publisherIdentifier) {
1787
- var _a;
1788
- return (_a = this._tmpSubscriberShelter.get(publisherIdentifier)) == null ? void 0 : _a.subscribers;
1421
+ this._exit();
1422
+ });
1789
1423
  }
1790
- // after adding publisher, it will change the temp subscriber to regular subscriber
1791
- _consumeTmpSubScribers(publisher, tmpSubScribers) {
1792
- tmpSubScribers.forEach((tmpSubScriber, identifier) => {
1424
+ _handleUnexpectedExit() {
1425
+ process.on("unhandledRejection", (error2) => {
1426
+ if (this._isReconnecting) {
1427
+ return;
1428
+ }
1429
+ console.error("Unhandled Rejection Error: ", error2);
1793
1430
  fileLog(
1794
- `notifyTmpSubScribers ${publisher.name} will be add a subscriber: ${identifier} `,
1795
- "Broker",
1796
- "warn"
1797
- );
1798
- publisher.addSubscriber(identifier, tmpSubScriber.client);
1799
- publisher.notifySubscriber(identifier, {
1800
- updateKind: "UPDATE_TYPE" /* UPDATE_TYPE */,
1801
- updateMode: "PASSIVE" /* PASSIVE */,
1802
- updateSourcePaths: [publisher.name],
1803
- remoteTypeTarPath: publisher.remoteTypeTarPath,
1804
- name: publisher.name
1805
- });
1431
+ `Process(${process.pid}) unhandledRejection, garfishModuleServer will exit...`,
1432
+ MF_SERVER_IDENTIFIER,
1433
+ "error"
1434
+ );
1435
+ this._exit();
1806
1436
  });
1807
- }
1808
- _clearTmpSubScriberRelation(identifier) {
1809
- this._tmpSubscriberShelter.delete(identifier);
1810
- }
1811
- _clearTmpSubScriberRelations() {
1812
- this._tmpSubscriberShelter.clear();
1813
- }
1814
- _disconnect() {
1815
- this._publisherMap.forEach((publisher) => {
1816
- publisher.close();
1437
+ process.on("uncaughtException", (error2) => {
1438
+ if (this._isReconnecting) {
1439
+ return;
1440
+ }
1441
+ console.error("Unhandled Exception Error: ", error2);
1442
+ fileLog(
1443
+ `Process(${process.pid}) uncaughtException, garfishModuleServer will exit...`,
1444
+ MF_SERVER_IDENTIFIER,
1445
+ "error"
1446
+ );
1447
+ this._exit();
1817
1448
  });
1818
1449
  }
1819
- // Every day on 0/6/9/12/15//18, Publishers that have not been connected within 1.5 hours will be cleared regularly.
1820
- // If process.env.FEDERATION_SERVER_TEST is set, it will be read at a specified time.
1821
- _setSchedule() {
1822
- const rule = new import_node_schedule.default.RecurrenceRule();
1823
- if (Number(process.env["FEDERATION_SERVER_TEST"])) {
1824
- const interval = Number(process.env["FEDERATION_SERVER_TEST"]) / 1e3;
1825
- const second = [];
1826
- for (let i = 0; i < 60; i = i + interval) {
1827
- second.push(i);
1828
- }
1829
- rule.second = second;
1830
- } else {
1831
- rule.second = 0;
1832
- rule.hour = [0, 3, 6, 9, 12, 15, 18];
1833
- rule.minute = 0;
1834
- }
1835
- const serverTest = Number(process.env["FEDERATION_SERVER_TEST"]);
1836
- this._scheduleJob = import_node_schedule.default.scheduleJob(rule, () => {
1837
- this._tmpSubscriberShelter.forEach((tmpSubscriber, identifier) => {
1450
+ _exit() {
1451
+ this._reconnect = false;
1452
+ if (this._publishWebSocket) {
1453
+ const exitPublisher = new ExitPublisherAction({
1454
+ name: this._name,
1455
+ ip: this._ip
1456
+ });
1457
+ this._publishWebSocket.send(JSON.stringify(exitPublisher));
1458
+ this._publishWebSocket.on("message", (message) => {
1459
+ const parsedMessage = JSON.parse(
1460
+ message.toString()
1461
+ );
1838
1462
  fileLog(
1839
- ` _clearTmpSubScriberRelation ${identifier}, ${Date.now() - tmpSubscriber.timestamp >= (process.env["GARFISH_MODULE_SERVER_TEST"] ? serverTest : _Broker.DEFAULT_WAITING_TIME)}`,
1840
- "Broker",
1463
+ `[${parsedMessage.kind}]: ${JSON.stringify(parsedMessage)}`,
1464
+ MF_SERVER_IDENTIFIER,
1841
1465
  "info"
1842
1466
  );
1843
- if (Date.now() - tmpSubscriber.timestamp >= (process.env["FEDERATION_SERVER_TEST"] ? serverTest : _Broker.DEFAULT_WAITING_TIME)) {
1844
- this._clearTmpSubScriberRelation(identifier);
1845
- }
1846
1467
  });
1847
- });
1848
- }
1849
- _clearSchedule() {
1850
- if (!this._scheduleJob) {
1851
- return;
1852
1468
  }
1853
- this._scheduleJob.cancel();
1854
- this._scheduleJob = null;
1855
- }
1856
- _stopWhenSIGTERMOrSIGINT() {
1857
- process.on("SIGTERM", () => {
1858
- this.exit();
1859
- });
1860
- process.on("SIGINT", () => {
1861
- this.exit();
1862
- });
1863
- }
1864
- _handleUnexpectedExit() {
1865
- process.on("unhandledRejection", (error2) => {
1866
- console.error("Unhandled Rejection Error: ", error2);
1867
- fileLog(`Unhandled Rejection Error: ${error2}`, "Broker", "fatal");
1868
- process.exit(1);
1869
- });
1870
- process.on("uncaughtException", (error2) => {
1871
- console.error("Unhandled Exception Error: ", error2);
1872
- fileLog(`Unhandled Rejection Error: ${error2}`, "Broker", "fatal");
1873
- process.exit(1);
1874
- });
1875
- }
1876
- async start() {
1469
+ if (this._publishWebSocket) {
1470
+ this._publishWebSocket.close();
1471
+ this._publishWebSocket = null;
1472
+ }
1473
+ process.exit(0);
1877
1474
  }
1878
1475
  exit() {
1879
- const brokerExitLog = new BrokerExitLog();
1880
- this.broadcast(JSON.stringify(brokerExitLog));
1881
- this._disconnect();
1882
- this._clearSchedule();
1883
- this._clearTmpSubScriberRelations();
1884
- this._webSocketServer && this._webSocketServer.close();
1885
- this._secureWebSocketServer && this._secureWebSocketServer.close();
1886
- process.exit(0);
1476
+ this._exit();
1887
1477
  }
1888
- broadcast(message) {
1889
- var _a, _b;
1478
+ update(options) {
1479
+ if (!this._publishWebSocket || !this._isConnected) {
1480
+ return;
1481
+ }
1482
+ const { updateKind, updateMode, updateSourcePaths } = options;
1890
1483
  fileLog(
1891
- `[broadcast] exit info : ${JSON.stringify(message)}`,
1892
- "Broker",
1893
- "warn"
1484
+ `update run, ${this._name} module update, updateKind: ${updateKind}, updateMode: ${updateMode}, updateSourcePaths: ${updateSourcePaths}`,
1485
+ MF_SERVER_IDENTIFIER,
1486
+ "info"
1894
1487
  );
1895
- (_a = this._webSocketServer) == null ? void 0 : _a.clients.forEach((client) => {
1896
- client.send(JSON.stringify(message));
1897
- });
1898
- (_b = this._secureWebSocketServer) == null ? void 0 : _b.clients.forEach((client) => {
1899
- client.send(JSON.stringify(message));
1488
+ if (updateKind === "RELOAD_PAGE" /* RELOAD_PAGE */) {
1489
+ const notifyWebClient = new NotifyWebClientAction({
1490
+ name: this._name,
1491
+ updateMode
1492
+ });
1493
+ this._publishWebSocket.send(JSON.stringify(notifyWebClient));
1494
+ return;
1495
+ }
1496
+ const updatePublisher = new UpdatePublisherAction({
1497
+ name: this._name,
1498
+ ip: this._ip,
1499
+ updateMode,
1500
+ updateKind,
1501
+ updateSourcePaths: [this._name],
1502
+ remoteTypeTarPath: this._remoteTypeTarPath
1900
1503
  });
1504
+ this._publishWebSocket.send(JSON.stringify(updatePublisher));
1901
1505
  }
1902
1506
  };
1903
- _Broker.WEB_SOCKET_CONNECT_MAGIC_ID = WEB_SOCKET_CONNECT_MAGIC_ID;
1904
- _Broker.DEFAULT_WEB_SOCKET_PORT = DEFAULT_WEB_SOCKET_PORT;
1905
- _Broker.DEFAULT_SECURE_WEB_SOCKET_PORT = 16324;
1906
- _Broker.DEFAULT_WAITING_TIME = 1.5 * 60 * 60 * 1e3;
1907
- var Broker = _Broker;
1908
1507
 
1909
- // packages/dts-plugin/src/server/broker/createBroker.ts
1910
- var import_child_process = require("child_process");
1911
- var import_path5 = __toESM(require("path"));
1912
- function createBroker() {
1913
- const startBrokerPath = import_path5.default.resolve(__dirname, "./startBroker.js");
1914
- const sub = (0, import_child_process.fork)(startBrokerPath, [], {
1915
- detached: true,
1916
- stdio: "ignore",
1917
- env: process.env
1508
+ // packages/dts-plugin/src/server/createKoaServer.ts
1509
+ var import_fs_extra = __toESM(require("fs-extra"));
1510
+ var import_koa = __toESM(require("koa"));
1511
+ async function createKoaServer(options) {
1512
+ const { typeTarPath } = options;
1513
+ const freeport = await getFreePort();
1514
+ const app = new import_koa.default();
1515
+ app.use(async (ctx, next) => {
1516
+ if (ctx.path === `/${DEFAULT_TAR_NAME}`) {
1517
+ ctx.status = 200;
1518
+ ctx.body = import_fs_extra.default.createReadStream(typeTarPath);
1519
+ ctx.response.type = "application/x-gzip";
1520
+ } else {
1521
+ await next();
1522
+ }
1918
1523
  });
1919
- sub.send("start");
1920
- sub.unref();
1921
- return sub;
1524
+ app.listen(freeport);
1525
+ return {
1526
+ server: app,
1527
+ serverAddress: `http://${getIPV4()}:${freeport}`
1528
+ };
1922
1529
  }
1923
1530
 
1924
- // packages/dts-plugin/src/server/DevServer.ts
1925
- var ModuleFederationDevServer = class {
1926
- constructor(ctx) {
1927
- this._publishWebSocket = null;
1928
- this._subscriberWebsocketMap = {};
1929
- this._reconnect = true;
1930
- this._reconnectTimes = 0;
1931
- this._isConnected = false;
1932
- this._isReconnecting = false;
1933
- this._updateCallback = () => Promise.resolve(void 0);
1934
- const { name, remotes, remoteTypeTarPath, updateCallback: updateCallback2 } = ctx;
1935
- this._ip = getIPV4();
1936
- this._name = name;
1937
- this._remotes = remotes;
1938
- this._remoteTypeTarPath = remoteTypeTarPath;
1939
- this._updateCallback = updateCallback2;
1940
- this._stopWhenSIGTERMOrSIGINT();
1941
- this._handleUnexpectedExit();
1942
- this._connectPublishToServer();
1943
- }
1944
- _connectPublishToServer() {
1945
- if (!this._reconnect) {
1946
- return;
1947
- }
1948
- fileLog(
1949
- `Publisher:${this._name} Trying to connect to ws://${this._ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}...`,
1950
- MF_SERVER_IDENTIFIER,
1951
- "info"
1952
- );
1953
- this._publishWebSocket = new import_isomorphic_ws2.default(
1954
- `ws://${this._ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}?WEB_SOCKET_CONNECT_MAGIC_ID=${Broker.WEB_SOCKET_CONNECT_MAGIC_ID}`
1531
+ // packages/dts-plugin/src/core/lib/archiveHandler.ts
1532
+ var retrieveTypesZipPath = (mfTypesPath, remoteOptions) => (0, import_path3.join)(
1533
+ mfTypesPath.replace(remoteOptions.typesFolder, ""),
1534
+ `${remoteOptions.typesFolder}.zip`
1535
+ );
1536
+ var createTypesArchive = async (tsConfig, remoteOptions) => {
1537
+ const mfTypesPath = retrieveMfTypesPath(tsConfig, remoteOptions);
1538
+ const zip = new import_adm_zip.default();
1539
+ zip.addLocalFolder(mfTypesPath);
1540
+ return zip.writeZipPromise(retrieveTypesZipPath(mfTypesPath, remoteOptions));
1541
+ };
1542
+ var downloadErrorLogger = (destinationFolder, fileToDownload) => (reason) => {
1543
+ throw {
1544
+ ...reason,
1545
+ message: `Network error: Unable to download federated mocks for '${destinationFolder}' from '${fileToDownload}' because '${reason.message}'`
1546
+ };
1547
+ };
1548
+ var retrieveTypesArchiveDestinationPath = (hostOptions, destinationFolder) => {
1549
+ return (0, import_path3.resolve)(
1550
+ hostOptions.context,
1551
+ hostOptions.typesFolder,
1552
+ destinationFolder
1553
+ );
1554
+ };
1555
+ var downloadTypesArchive = (hostOptions) => {
1556
+ let retries = 0;
1557
+ return async ([destinationFolder, fileToDownload]) => {
1558
+ const destinationPath = retrieveTypesArchiveDestinationPath(
1559
+ hostOptions,
1560
+ destinationFolder
1955
1561
  );
1956
- this._publishWebSocket.on("open", () => {
1957
- var _a;
1958
- fileLog(
1959
- `Current pid: ${process.pid}, publisher:${this._name} connected to ws://${this._ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}, starting service...`,
1960
- MF_SERVER_IDENTIFIER,
1961
- "info"
1962
- );
1963
- this._isConnected = true;
1964
- const startGarfishModule = new AddPublisherAction({
1965
- name: this._name,
1966
- ip: this._ip,
1967
- remoteTypeTarPath: this._remoteTypeTarPath
1968
- });
1969
- (_a = this._publishWebSocket) == null ? void 0 : _a.send(JSON.stringify(startGarfishModule));
1970
- this._connectSubscribers();
1971
- });
1972
- this._publishWebSocket.on("message", (message) => {
1973
- var _a, _b;
1562
+ while (retries++ < hostOptions.maxRetries) {
1974
1563
  try {
1975
- const parsedMessage = JSON.parse(
1976
- message.toString()
1564
+ const url = replaceLocalhost(fileToDownload);
1565
+ const response = await import_axios.default.get(url, { responseType: "arraybuffer" }).catch(downloadErrorLogger(destinationFolder, url));
1566
+ const zip = new import_adm_zip.default(Buffer.from(response.data));
1567
+ zip.extractAllTo(destinationPath, true);
1568
+ return [destinationFolder, destinationPath];
1569
+ } catch (error2) {
1570
+ fileLog(
1571
+ `Error during types archive download: ${(error2 == null ? void 0 : error2.message) || "unknown error"}`,
1572
+ "downloadTypesArchive",
1573
+ "error"
1977
1574
  );
1978
- if (parsedMessage.type === "Log") {
1979
- if (parsedMessage.kind === "BrokerExitLog" /* BrokerExitLog */) {
1980
- fileLog(
1981
- `Receive broker exit signal, ${this._name} service will exit...`,
1982
- MF_SERVER_IDENTIFIER,
1983
- "warn"
1984
- );
1985
- this._exit();
1575
+ if (retries >= hostOptions.maxRetries) {
1576
+ if (hostOptions.abortOnError !== false) {
1577
+ throw error2;
1986
1578
  }
1579
+ return void 0;
1987
1580
  }
1988
- } catch (err) {
1989
- console.error(err);
1990
- const exitPublisher = new ExitPublisherAction({
1991
- name: this._name,
1992
- ip: this._ip
1993
- });
1994
- const exitSubscriber = new ExitSubscriberAction({
1995
- name: this._name,
1996
- ip: this._ip,
1997
- publishers: this._remotes.map((remote) => ({
1998
- name: remote.name,
1999
- ip: remote.ip
2000
- }))
2001
- });
2002
- (_a = this._publishWebSocket) == null ? void 0 : _a.send(JSON.stringify(exitPublisher));
2003
- (_b = this._publishWebSocket) == null ? void 0 : _b.send(JSON.stringify(exitSubscriber));
2004
- fileLog(
2005
- "Parse messages error, ModuleFederationDevServer will exit...",
2006
- MF_SERVER_IDENTIFIER,
2007
- "fatal"
2008
- );
2009
- this._exit();
2010
- }
2011
- });
2012
- this._publishWebSocket.on("close", (code) => {
2013
- fileLog(
2014
- `Connection closed with code ${code}.`,
2015
- MF_SERVER_IDENTIFIER,
2016
- "warn"
2017
- );
2018
- this._publishWebSocket && this._publishWebSocket.close();
2019
- this._publishWebSocket = null;
2020
- if (!this._reconnect) {
2021
- return;
2022
1581
  }
2023
- const reconnectTime = fib(++this._reconnectTimes);
2024
- fileLog(
2025
- `start reconnecting to server after ${reconnectTime}s.`,
2026
- MF_SERVER_IDENTIFIER,
2027
- "info"
2028
- );
2029
- setTimeout(() => this._connectPublishToServer(), reconnectTime * 1e3);
2030
- });
2031
- this._publishWebSocket.on(
2032
- "error",
2033
- this._tryCreateBackgroundBroker.bind(this)
2034
- );
1582
+ }
1583
+ };
1584
+ };
1585
+
1586
+ // packages/dts-plugin/src/core/configurations/hostPlugin.ts
1587
+ var import_sdk3 = require("@module-federation/sdk");
1588
+ var import_managers = require("@module-federation/managers");
1589
+ var defaultOptions = {
1590
+ typesFolder: "@mf-types",
1591
+ remoteTypesFolder: "@mf-types",
1592
+ deleteTypesFolder: true,
1593
+ maxRetries: 3,
1594
+ implementation: "",
1595
+ context: process.cwd(),
1596
+ abortOnError: true,
1597
+ consumeAPITypes: false
1598
+ };
1599
+ var buildZipUrl = (hostOptions, url) => {
1600
+ const remoteUrl = new URL(url);
1601
+ if (remoteUrl.href.includes(import_sdk3.MANIFEST_EXT)) {
1602
+ return void 0;
2035
1603
  }
2036
- // Associate the remotes(Subscriber) to the Broker
2037
- _connectSubscriberToServer(remote) {
2038
- const { name, ip } = remote;
2039
- fileLog(
2040
- `remote module:${name} trying to connect to ws://${ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}...`,
2041
- MF_SERVER_IDENTIFIER,
2042
- "info"
2043
- );
2044
- const identifier = getIdentifier({
2045
- name,
2046
- ip
2047
- });
2048
- this._subscriberWebsocketMap[identifier] = new import_isomorphic_ws2.default(
2049
- `ws://${ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}?WEB_SOCKET_CONNECT_MAGIC_ID=${Broker.WEB_SOCKET_CONNECT_MAGIC_ID}`
2050
- );
2051
- this._subscriberWebsocketMap[identifier].on("open", () => {
2052
- fileLog(
2053
- `Current pid: ${process.pid} remote module: ${name} connected to ws://${ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}, starting service...`,
2054
- MF_SERVER_IDENTIFIER,
2055
- "info"
2056
- );
2057
- const addSubscriber = new AddSubscriberAction({
2058
- name: this._name,
2059
- // module self name
2060
- ip: this._ip,
2061
- publishers: [
2062
- {
2063
- name,
2064
- // remote's name
2065
- ip
2066
- }
2067
- ]
1604
+ const pathnameWithoutEntry = remoteUrl.pathname.split("/").slice(0, -1).join("/");
1605
+ remoteUrl.pathname = `${pathnameWithoutEntry}/${hostOptions.remoteTypesFolder}.zip`;
1606
+ return remoteUrl.href;
1607
+ };
1608
+ var buildApiTypeUrl = (zipUrl) => {
1609
+ if (!zipUrl) {
1610
+ return void 0;
1611
+ }
1612
+ return zipUrl.replace(".zip", ".d.ts");
1613
+ };
1614
+ var retrieveRemoteInfo = (options) => {
1615
+ const { hostOptions, remoteAlias, remote } = options;
1616
+ const parsedInfo = (0, import_sdk3.parseEntry)(remote, void 0, "@");
1617
+ const url = "entry" in parsedInfo ? parsedInfo.entry : parsedInfo.name === remote ? remote : "";
1618
+ const zipUrl = url ? buildZipUrl(hostOptions, url) : "";
1619
+ return {
1620
+ name: parsedInfo.name || remoteAlias,
1621
+ url,
1622
+ zipUrl,
1623
+ apiTypeUrl: buildApiTypeUrl(zipUrl),
1624
+ alias: remoteAlias
1625
+ };
1626
+ };
1627
+ var resolveRemotes = (hostOptions) => {
1628
+ const parsedOptions = import_managers.utils.parseOptions(
1629
+ hostOptions.moduleFederationConfig.remotes || {},
1630
+ (item, key) => ({
1631
+ remote: Array.isArray(item) ? item[0] : item,
1632
+ key
1633
+ }),
1634
+ (item, key) => ({
1635
+ remote: Array.isArray(item.external) ? item.external[0] : item.external,
1636
+ key
1637
+ })
1638
+ );
1639
+ return parsedOptions.reduce(
1640
+ (accumulator, item) => {
1641
+ const { key, remote } = item[1];
1642
+ accumulator[key] = retrieveRemoteInfo({
1643
+ hostOptions,
1644
+ remoteAlias: key,
1645
+ remote
2068
1646
  });
2069
- this._subscriberWebsocketMap[identifier].send(
2070
- JSON.stringify(addSubscriber)
2071
- );
2072
- });
2073
- this._subscriberWebsocketMap[identifier].on("message", async (message) => {
2074
- try {
2075
- const parsedMessage = JSON.parse(
2076
- message.toString()
2077
- );
2078
- if (parsedMessage.type === "Log") {
2079
- if (parsedMessage.kind === "BrokerExitLog" /* BrokerExitLog */) {
2080
- fileLog(
2081
- `${identifier}'s Server exit, thus ${identifier} will no longer has reload ability.`,
2082
- MF_SERVER_IDENTIFIER,
2083
- "warn"
2084
- );
2085
- this._exit();
2086
- }
2087
- }
2088
- if (parsedMessage.type === "API") {
2089
- if (parsedMessage.kind === "UPDATE_SUBSCRIBER" /* UPDATE_SUBSCRIBER */) {
2090
- const {
2091
- payload: {
2092
- updateKind,
2093
- updateSourcePaths,
2094
- name: subscribeName,
2095
- remoteTypeTarPath,
2096
- updateMode
2097
- }
2098
- } = parsedMessage;
2099
- await this._updateSubscriber({
2100
- remoteTypeTarPath,
2101
- name: subscribeName,
2102
- updateKind,
2103
- updateMode,
2104
- updateSourcePaths
2105
- });
2106
- }
2107
- }
2108
- } catch (err) {
2109
- console.error(err);
2110
- const exitSubscriber = new ExitSubscriberAction({
2111
- name: this._name,
2112
- ip: this._ip,
2113
- publishers: [
2114
- {
2115
- name,
2116
- ip
2117
- }
2118
- ]
2119
- });
2120
- this._subscriberWebsocketMap[identifier].send(
2121
- JSON.stringify(exitSubscriber)
2122
- );
2123
- fileLog(
2124
- `${identifier} exit,
2125
- error: ${err instanceof Error ? err.toString() : JSON.stringify(err)}
2126
- `,
2127
- MF_SERVER_IDENTIFIER,
2128
- "warn"
2129
- );
1647
+ return accumulator;
1648
+ },
1649
+ {}
1650
+ );
1651
+ };
1652
+ var retrieveHostConfig = (options) => {
1653
+ validateOptions(options);
1654
+ const hostOptions = { ...defaultOptions, ...options };
1655
+ const mapRemotesToDownload = resolveRemotes(hostOptions);
1656
+ return {
1657
+ hostOptions,
1658
+ mapRemotesToDownload
1659
+ };
1660
+ };
1661
+
1662
+ // packages/dts-plugin/src/core/constant.ts
1663
+ var REMOTE_ALIAS_IDENTIFIER = "REMOTE_ALIAS_IDENTIFIER";
1664
+ var REMOTE_API_TYPES_FILE_NAME = "apis.d.ts";
1665
+ var HOST_API_TYPES_FILE_NAME = "index.d.ts";
1666
+
1667
+ // packages/dts-plugin/src/core/lib/DTSManager.ts
1668
+ var import_axios2 = __toESM(require("axios"));
1669
+ var DTSManager = class {
1670
+ constructor(options) {
1671
+ this.options = (0, import_lodash.default)(options, (_value, key) => {
1672
+ if (key === "manifest") {
1673
+ return false;
2130
1674
  }
2131
1675
  });
2132
- this._subscriberWebsocketMap[identifier].on("close", (code) => {
2133
- fileLog(
2134
- `Connection closed with code ${code}.`,
2135
- MF_SERVER_IDENTIFIER,
2136
- "warn"
2137
- );
2138
- this._subscriberWebsocketMap[identifier] && this._subscriberWebsocketMap[identifier].close();
2139
- delete this._subscriberWebsocketMap[identifier];
2140
- });
1676
+ this.runtimePkgs = [
1677
+ "@module-federation/runtime",
1678
+ "@module-federation/enhanced/runtime",
1679
+ "@module-federation/runtime-tools"
1680
+ ];
1681
+ this.loadedRemoteAPIAlias = [];
1682
+ this.remoteAliasMap = {};
1683
+ this.extraOptions = (options == null ? void 0 : options.extraOptions) || {};
2141
1684
  }
2142
- _connectSubscribers() {
2143
- this._remotes.forEach((remote) => {
2144
- this._connectSubscriberToServer(remote);
2145
- });
1685
+ generateAPITypes(mapComponentsToExpose) {
1686
+ const exposePaths = /* @__PURE__ */ new Set();
1687
+ const packageType = Object.keys(mapComponentsToExpose).reduce(
1688
+ (sum, exposeKey) => {
1689
+ const exposePath = import_path4.default.join(REMOTE_ALIAS_IDENTIFIER, exposeKey);
1690
+ exposePaths.add(`'${exposePath}'`);
1691
+ const curType = `T extends '${exposePath}' ? typeof import('${exposePath}') :`;
1692
+ sum = curType + sum;
1693
+ return sum;
1694
+ },
1695
+ "any;"
1696
+ );
1697
+ const exposePathKeys = [...exposePaths].join(" | ");
1698
+ return `
1699
+ export type RemoteKeys = ${exposePathKeys};
1700
+ type PackageType<T> = ${packageType}`;
2146
1701
  }
2147
- // app1 consumes provider1. And the function will be triggered when provider1 code change.
2148
- async _updateSubscriber(options) {
1702
+ async extractRemoteTypes(options) {
1703
+ const { remoteOptions, tsConfig } = options;
1704
+ if (!remoteOptions.extractRemoteTypes) {
1705
+ return;
1706
+ }
1707
+ let hasRemotes = false;
1708
+ const remotes = remoteOptions.moduleFederationConfig.remotes;
1709
+ if (remotes) {
1710
+ if (Array.isArray(remotes)) {
1711
+ hasRemotes = Boolean(remotes.length);
1712
+ } else if (typeof remotes === "object") {
1713
+ hasRemotes = Boolean(Object.keys(remotes).length);
1714
+ }
1715
+ }
1716
+ const mfTypesPath = retrieveMfTypesPath(tsConfig, remoteOptions);
1717
+ if (hasRemotes) {
1718
+ const tempHostOptions = {
1719
+ moduleFederationConfig: remoteOptions.moduleFederationConfig,
1720
+ typesFolder: import_path4.default.join(mfTypesPath, "node_modules"),
1721
+ remoteTypesFolder: (remoteOptions == null ? void 0 : remoteOptions.hostRemoteTypesFolder) || remoteOptions.typesFolder,
1722
+ deleteTypesFolder: true,
1723
+ context: remoteOptions.context,
1724
+ implementation: remoteOptions.implementation,
1725
+ abortOnError: false
1726
+ };
1727
+ await this.consumeArchiveTypes(tempHostOptions);
1728
+ }
1729
+ }
1730
+ async generateTypes() {
2149
1731
  var _a;
2150
- const {
2151
- updateMode,
2152
- updateKind,
2153
- updateSourcePaths,
2154
- name,
2155
- remoteTypeTarPath
2156
- } = options;
2157
- if (updateMode === "PASSIVE" /* PASSIVE */ && updateSourcePaths.includes(this._name)) {
1732
+ try {
1733
+ const { options } = this;
1734
+ if (!options.remote) {
1735
+ throw new Error(
1736
+ "options.remote is required if you want to generateTypes"
1737
+ );
1738
+ }
1739
+ const { remoteOptions, tsConfig, mapComponentsToExpose } = retrieveRemoteConfig(options.remote);
1740
+ if (!Object.keys(mapComponentsToExpose).length) {
1741
+ return;
1742
+ }
1743
+ this.extractRemoteTypes({
1744
+ remoteOptions,
1745
+ tsConfig,
1746
+ mapComponentsToExpose
1747
+ });
1748
+ compileTs(mapComponentsToExpose, tsConfig, remoteOptions);
1749
+ await createTypesArchive(tsConfig, remoteOptions);
1750
+ let apiTypesPath = "";
1751
+ if (remoteOptions.generateAPITypes) {
1752
+ const apiTypes = this.generateAPITypes(mapComponentsToExpose);
1753
+ apiTypesPath = retrieveMfAPITypesPath(tsConfig, remoteOptions);
1754
+ import_fs.default.writeFileSync(apiTypesPath, apiTypes);
1755
+ }
1756
+ if (remoteOptions.deleteTypesFolder) {
1757
+ await (0, import_promises.rm)(retrieveMfTypesPath(tsConfig, remoteOptions), {
1758
+ recursive: true,
1759
+ force: true
1760
+ });
1761
+ }
1762
+ console.log(import_ansi_colors2.default.green("Federated types created correctly"));
1763
+ } catch (error2) {
1764
+ if (((_a = this.options.remote) == null ? void 0 : _a.abortOnError) === false) {
1765
+ console.error(
1766
+ import_ansi_colors2.default.red(`Unable to compile federated types, ${error2}`)
1767
+ );
1768
+ } else {
1769
+ throw error2;
1770
+ }
1771
+ }
1772
+ }
1773
+ async requestRemoteManifest(remoteInfo) {
1774
+ try {
1775
+ if (!remoteInfo.url.includes(import_sdk4.MANIFEST_EXT)) {
1776
+ return remoteInfo;
1777
+ }
1778
+ const url = replaceLocalhost(remoteInfo.url);
1779
+ const res = await (0, import_axios2.default)({
1780
+ method: "get",
1781
+ url
1782
+ });
1783
+ const manifestJson = res.data;
1784
+ if (!manifestJson.metaData.types.zip) {
1785
+ throw new Error(`Can not get ${remoteInfo.name}'s types archive url!`);
1786
+ }
1787
+ const addProtocol = (u) => {
1788
+ if (u.startsWith("//")) {
1789
+ return `https:${u}`;
1790
+ }
1791
+ return u;
1792
+ };
1793
+ const publicPath = "publicPath" in manifestJson.metaData ? manifestJson.metaData.publicPath : new Function(manifestJson.metaData.getPublicPath)();
1794
+ remoteInfo.zipUrl = new URL(
1795
+ import_path4.default.join(addProtocol(publicPath), manifestJson.metaData.types.zip)
1796
+ ).href;
1797
+ if (!manifestJson.metaData.types.api) {
1798
+ console.warn(`Can not get ${remoteInfo.name}'s api types url!`);
1799
+ remoteInfo.apiTypeUrl = "";
1800
+ return remoteInfo;
1801
+ }
1802
+ remoteInfo.apiTypeUrl = new URL(
1803
+ import_path4.default.join(addProtocol(publicPath), manifestJson.metaData.types.api)
1804
+ ).href;
1805
+ return remoteInfo;
1806
+ } catch (_err) {
2158
1807
  fileLog(
2159
- // eslint-disable-next-line max-len
2160
- `[_updateSubscriber] run, updateSourcePaths:${updateSourcePaths} includes ${this._name}, update ignore!`,
2161
- MF_SERVER_IDENTIFIER,
2162
- "warn"
1808
+ `fetch manifest failed, ${_err}, ${remoteInfo.name} will be ignored`,
1809
+ "requestRemoteManifest",
1810
+ "error"
2163
1811
  );
1812
+ return remoteInfo;
1813
+ }
1814
+ }
1815
+ async consumeTargetRemotes(hostOptions, remoteInfo) {
1816
+ if (!remoteInfo.zipUrl) {
1817
+ throw new Error(`Can not get ${remoteInfo.name}'s types archive url!`);
1818
+ }
1819
+ const typesDownloader = downloadTypesArchive(hostOptions);
1820
+ return typesDownloader([remoteInfo.alias, remoteInfo.zipUrl]);
1821
+ }
1822
+ async downloadAPITypes(remoteInfo, destinationPath) {
1823
+ const { apiTypeUrl } = remoteInfo;
1824
+ if (!apiTypeUrl) {
2164
1825
  return;
2165
1826
  }
2166
- if (updateSourcePaths.slice(-1)[0] === this._name) {
1827
+ try {
1828
+ const url = replaceLocalhost(apiTypeUrl);
1829
+ const res = await import_axios2.default.get(url);
1830
+ let apiTypeFile = res.data;
1831
+ apiTypeFile = apiTypeFile.replaceAll(
1832
+ REMOTE_ALIAS_IDENTIFIER,
1833
+ remoteInfo.alias
1834
+ );
1835
+ const filePath = import_path4.default.join(destinationPath, REMOTE_API_TYPES_FILE_NAME);
1836
+ import_fs.default.writeFileSync(filePath, apiTypeFile);
1837
+ this.loadedRemoteAPIAlias.push(remoteInfo.alias);
1838
+ } catch (err) {
2167
1839
  fileLog(
2168
- `[_updateSubscriber] run, updateSourcePaths:${updateSourcePaths} ends is ${this._name}, update ignore!`,
2169
- MF_SERVER_IDENTIFIER,
2170
- "warn"
1840
+ `Unable to download "${remoteInfo.name}" api types, ${err}`,
1841
+ "consumeTargetRemotes",
1842
+ "error"
2171
1843
  );
2172
- return;
2173
1844
  }
2174
- fileLog(
2175
- // eslint-disable-next-line max-len
2176
- `[_updateSubscriber] run, updateSourcePaths:${updateSourcePaths}, current module:${this._name}, update start...`,
2177
- MF_SERVER_IDENTIFIER,
2178
- "info"
2179
- );
2180
- await this._updateCallback({
2181
- name,
2182
- updateMode,
2183
- updateKind,
2184
- updateSourcePaths,
2185
- remoteTypeTarPath
2186
- });
2187
- const newUpdateSourcePaths = updateSourcePaths.concat(this._name);
2188
- const updatePublisher = new UpdatePublisherAction({
2189
- name: this._name,
2190
- ip: this._ip,
2191
- updateMode: "PASSIVE" /* PASSIVE */,
2192
- updateKind,
2193
- updateSourcePaths: newUpdateSourcePaths,
2194
- remoteTypeTarPath: this._remoteTypeTarPath
2195
- });
2196
- fileLog(
2197
- // eslint-disable-next-line max-len
2198
- `[_updateSubscriber] run, updateSourcePaths:${newUpdateSourcePaths}, update publisher ${this._name} start...`,
2199
- MF_SERVER_IDENTIFIER,
2200
- "info"
2201
- );
2202
- (_a = this._publishWebSocket) == null ? void 0 : _a.send(JSON.stringify(updatePublisher));
2203
1845
  }
2204
- _tryCreateBackgroundBroker(err) {
2205
- if (!((err == null ? void 0 : err.code) === "ECONNREFUSED" && err.port === Broker.DEFAULT_WEB_SOCKET_PORT)) {
2206
- fileLog(`websocket error: ${err.stack}`, MF_SERVER_IDENTIFIER, "fatal");
1846
+ consumeAPITypes(hostOptions) {
1847
+ if (!this.loadedRemoteAPIAlias.length) {
2207
1848
  return;
2208
1849
  }
2209
- fileLog(
2210
- `Failed to connect to ws://${this._ip}:${Broker.DEFAULT_WEB_SOCKET_PORT}...`,
2211
- MF_SERVER_IDENTIFIER,
2212
- "fatal"
1850
+ const packageTypes = [];
1851
+ const remoteKeys = [];
1852
+ const importTypeStr = this.loadedRemoteAPIAlias.map((alias, index) => {
1853
+ const remoteKey = `RemoteKeys_${index}`;
1854
+ const packageType = `PackageType_${index}`;
1855
+ packageTypes.push(`T extends ${remoteKey} ? ${packageType}<T>`);
1856
+ remoteKeys.push(remoteKey);
1857
+ return `import type { PackageType as ${packageType},RemoteKeys as ${remoteKey} } from './${alias}/apis.d.ts';`;
1858
+ }).join("\n");
1859
+ const remoteKeysStr = `type RemoteKeys = ${remoteKeys.join(" | ")};`;
1860
+ const packageTypesStr = `type PackageType<T, Y=any> = ${[
1861
+ ...packageTypes,
1862
+ "Y"
1863
+ ].join(" :\n")} ;`;
1864
+ const pkgsDeclareStr = this.runtimePkgs.map((pkg) => {
1865
+ return `declare module "${pkg}" {
1866
+ ${remoteKeysStr}
1867
+ ${packageTypesStr}
1868
+ export function loadRemote<T extends RemoteKeys,Y>(packageName: T): Promise<PackageType<T, Y>>;
1869
+ export function loadRemote<T extends string,Y>(packageName: T): Promise<PackageType<T, Y>>;
1870
+ }`;
1871
+ }).join("\n");
1872
+ const fileStr = `${importTypeStr}
1873
+ ${pkgsDeclareStr}
1874
+ `;
1875
+ import_fs.default.writeFileSync(
1876
+ import_path4.default.join(
1877
+ hostOptions.context,
1878
+ hostOptions.typesFolder,
1879
+ HOST_API_TYPES_FILE_NAME
1880
+ ),
1881
+ fileStr
2213
1882
  );
2214
- this._isReconnecting = true;
2215
- setTimeout(
2216
- () => {
2217
- this._isReconnecting = false;
2218
- if (this._reconnect === false) {
2219
- return;
2220
- }
2221
- fileLog(
2222
- "Creating new background broker...",
2223
- MF_SERVER_IDENTIFIER,
2224
- "warn"
1883
+ }
1884
+ async consumeArchiveTypes(options) {
1885
+ const { hostOptions, mapRemotesToDownload } = retrieveHostConfig(options);
1886
+ if (hostOptions.deleteTypesFolder) {
1887
+ await (0, import_promises.rm)(hostOptions.typesFolder, {
1888
+ recursive: true,
1889
+ force: true
1890
+ }).catch(
1891
+ (error2) => fileLog(
1892
+ `Unable to remove types folder, ${error2}`,
1893
+ "consumeArchiveTypes",
1894
+ "error"
1895
+ )
1896
+ );
1897
+ }
1898
+ const downloadPromises = Object.entries(mapRemotesToDownload).map(
1899
+ async (item) => {
1900
+ const remoteInfo = item[1];
1901
+ if (!this.remoteAliasMap[remoteInfo.alias]) {
1902
+ const requiredRemoteInfo = await this.requestRemoteManifest(remoteInfo);
1903
+ this.remoteAliasMap[remoteInfo.alias] = requiredRemoteInfo;
1904
+ }
1905
+ return this.consumeTargetRemotes(
1906
+ hostOptions,
1907
+ this.remoteAliasMap[remoteInfo.alias]
2225
1908
  );
2226
- const broker = createBroker();
2227
- broker.on("message", (message) => {
2228
- if (message === "ready") {
2229
- fileLog("background broker started.", MF_SERVER_IDENTIFIER, "info");
2230
- this._reconnectTimes = 1;
2231
- if (process.send) {
2232
- process.send("ready");
1909
+ }
1910
+ );
1911
+ const downloadPromisesResult = await Promise.allSettled(downloadPromises);
1912
+ return {
1913
+ hostOptions,
1914
+ downloadPromisesResult
1915
+ };
1916
+ }
1917
+ async consumeTypes() {
1918
+ var _a;
1919
+ try {
1920
+ const { options } = this;
1921
+ if (!options.host) {
1922
+ throw new Error("options.host is required if you want to consumeTypes");
1923
+ }
1924
+ const { mapRemotesToDownload } = retrieveHostConfig(options.host);
1925
+ if (!Object.keys(mapRemotesToDownload).length) {
1926
+ return;
1927
+ }
1928
+ const { downloadPromisesResult, hostOptions } = await this.consumeArchiveTypes(options.host);
1929
+ if (hostOptions.consumeAPITypes) {
1930
+ await Promise.all(
1931
+ downloadPromisesResult.map(async (item) => {
1932
+ if (item.status === "rejected" || !item.value) {
1933
+ return;
2233
1934
  }
2234
- }
1935
+ const [alias, destinationPath] = item.value;
1936
+ const remoteInfo = this.remoteAliasMap[alias];
1937
+ if (!remoteInfo) {
1938
+ return;
1939
+ }
1940
+ await this.downloadAPITypes(remoteInfo, destinationPath);
1941
+ })
1942
+ );
1943
+ this.consumeAPITypes(hostOptions);
1944
+ }
1945
+ console.log(import_ansi_colors2.default.green("Federated types extraction completed"));
1946
+ } catch (err) {
1947
+ if (((_a = this.options.host) == null ? void 0 : _a.abortOnError) === false) {
1948
+ fileLog(
1949
+ `Unable to consume federated types, ${err}`,
1950
+ "consumeTypes",
1951
+ "error"
1952
+ );
1953
+ } else {
1954
+ throw err;
1955
+ }
1956
+ }
1957
+ }
1958
+ async updateTypes(options) {
1959
+ var _a, _b, _c;
1960
+ const { remoteName, updateMode } = options;
1961
+ const hostName = (_c = (_b = (_a = this.options) == null ? void 0 : _a.host) == null ? void 0 : _b.moduleFederationConfig) == null ? void 0 : _c.name;
1962
+ if (updateMode === "POSITIVE" /* POSITIVE */ && remoteName === hostName) {
1963
+ if (!this.options.remote) {
1964
+ return;
1965
+ }
1966
+ this.generateTypes();
1967
+ } else {
1968
+ const { remoteAliasMap } = this;
1969
+ if (!this.options.host) {
1970
+ return;
1971
+ }
1972
+ const { hostOptions, mapRemotesToDownload } = retrieveHostConfig(
1973
+ this.options.host
1974
+ );
1975
+ const loadedRemoteInfo = Object.values(remoteAliasMap).find(
1976
+ (i) => i.name === remoteName
1977
+ );
1978
+ if (!loadedRemoteInfo) {
1979
+ const remoteInfo = Object.values(mapRemotesToDownload).find((item) => {
1980
+ return item.name === remoteName;
2235
1981
  });
2236
- },
2237
- Math.ceil(100 * Math.random())
1982
+ if (remoteInfo) {
1983
+ if (!this.remoteAliasMap[remoteInfo.alias]) {
1984
+ const requiredRemoteInfo = await this.requestRemoteManifest(remoteInfo);
1985
+ this.remoteAliasMap[remoteInfo.alias] = requiredRemoteInfo;
1986
+ }
1987
+ await this.consumeTargetRemotes(
1988
+ hostOptions,
1989
+ this.remoteAliasMap[remoteInfo.alias]
1990
+ );
1991
+ }
1992
+ } else {
1993
+ await this.consumeTargetRemotes(hostOptions, loadedRemoteInfo);
1994
+ }
1995
+ }
1996
+ }
1997
+ };
1998
+
1999
+ // packages/dts-plugin/src/core/lib/utils.ts
2000
+ var import_ansi_colors3 = __toESM(require("ansi-colors"));
2001
+ function getDTSManagerConstructor(implementation) {
2002
+ if (implementation) {
2003
+ const NewConstructor = require(implementation);
2004
+ return NewConstructor.default ? NewConstructor.default : NewConstructor;
2005
+ }
2006
+ return DTSManager;
2007
+ }
2008
+ var validateOptions = (options) => {
2009
+ if (!options.moduleFederationConfig) {
2010
+ throw new Error("moduleFederationConfig is required");
2011
+ }
2012
+ };
2013
+ function replaceLocalhost(url) {
2014
+ return url.replace("localhost", "127.0.0.1");
2015
+ }
2016
+
2017
+ // packages/dts-plugin/src/core/configurations/remotePlugin.ts
2018
+ var defaultOptions2 = {
2019
+ tsConfigPath: "./tsconfig.json",
2020
+ typesFolder: "@mf-types",
2021
+ compiledTypesFolder: "compiled-types",
2022
+ hostRemoteTypesFolder: "@mf-types",
2023
+ deleteTypesFolder: true,
2024
+ additionalFilesToCompile: [],
2025
+ compilerInstance: "tsc",
2026
+ compileInChildProcess: false,
2027
+ implementation: "",
2028
+ generateAPITypes: false,
2029
+ context: process.cwd(),
2030
+ abortOnError: true,
2031
+ extractRemoteTypes: false,
2032
+ extractThirdParty: false
2033
+ };
2034
+ var readTsConfig = ({
2035
+ tsConfigPath,
2036
+ typesFolder,
2037
+ compiledTypesFolder,
2038
+ context
2039
+ }) => {
2040
+ const resolvedTsConfigPath = (0, import_path5.resolve)(context, tsConfigPath);
2041
+ const readResult = import_typescript2.default.readConfigFile(
2042
+ resolvedTsConfigPath,
2043
+ import_typescript2.default.sys.readFile
2044
+ );
2045
+ if (readResult.error) {
2046
+ throw new Error(readResult.error.messageText.toString());
2047
+ }
2048
+ const configContent = import_typescript2.default.parseJsonConfigFileContent(
2049
+ readResult.config,
2050
+ import_typescript2.default.sys,
2051
+ (0, import_path5.dirname)(resolvedTsConfigPath)
2052
+ );
2053
+ const outDir = (0, import_path5.resolve)(
2054
+ context,
2055
+ configContent.options.outDir || "dist",
2056
+ typesFolder,
2057
+ compiledTypesFolder
2058
+ );
2059
+ return {
2060
+ ...configContent.options,
2061
+ emitDeclarationOnly: true,
2062
+ noEmit: false,
2063
+ declaration: true,
2064
+ outDir
2065
+ };
2066
+ };
2067
+ var TS_EXTENSIONS = ["ts", "tsx", "vue", "svelte"];
2068
+ var resolveWithExtension = (exposedPath, context) => {
2069
+ if ((0, import_path5.extname)(exposedPath)) {
2070
+ return (0, import_path5.resolve)(context, exposedPath);
2071
+ }
2072
+ for (const extension of TS_EXTENSIONS) {
2073
+ const exposedPathWithExtension = (0, import_path5.resolve)(
2074
+ context,
2075
+ `${exposedPath}.${extension}`
2238
2076
  );
2077
+ if ((0, import_fs2.existsSync)(exposedPathWithExtension)) {
2078
+ return exposedPathWithExtension;
2079
+ }
2080
+ }
2081
+ return void 0;
2082
+ };
2083
+ var resolveExposes = (remoteOptions) => {
2084
+ const parsedOptions = import_managers2.utils.parseOptions(
2085
+ remoteOptions.moduleFederationConfig.exposes || {},
2086
+ (item, key) => ({
2087
+ exposePath: Array.isArray(item) ? item[0] : item,
2088
+ key
2089
+ }),
2090
+ (item, key) => ({
2091
+ exposePath: Array.isArray(item.import) ? item.import[0] : item.import[0],
2092
+ key
2093
+ })
2094
+ );
2095
+ return parsedOptions.reduce(
2096
+ (accumulator, item) => {
2097
+ const { exposePath, key } = item[1];
2098
+ accumulator[key] = resolveWithExtension(exposePath, remoteOptions.context) || resolveWithExtension(
2099
+ (0, import_path5.join)(exposePath, "index"),
2100
+ remoteOptions.context
2101
+ ) || exposePath;
2102
+ return accumulator;
2103
+ },
2104
+ {}
2105
+ );
2106
+ };
2107
+ var retrieveRemoteConfig = (options) => {
2108
+ validateOptions(options);
2109
+ const remoteOptions = {
2110
+ ...defaultOptions2,
2111
+ ...options
2112
+ };
2113
+ const mapComponentsToExpose = resolveExposes(remoteOptions);
2114
+ const tsConfig = readTsConfig(remoteOptions);
2115
+ return {
2116
+ tsConfig,
2117
+ mapComponentsToExpose,
2118
+ remoteOptions
2119
+ };
2120
+ };
2121
+
2122
+ // packages/dts-plugin/src/core/lib/DtsWorker.ts
2123
+ var import_lodash2 = __toESM(require("lodash.clonedeepwith"));
2124
+
2125
+ // packages/dts-plugin/src/core/rpc/index.ts
2126
+ var rpc_exports = {};
2127
+ __export(rpc_exports, {
2128
+ RpcExitError: () => RpcExitError,
2129
+ RpcGMCallTypes: () => RpcGMCallTypes,
2130
+ createRpcWorker: () => createRpcWorker,
2131
+ exposeRpc: () => exposeRpc,
2132
+ getRpcWorkerData: () => getRpcWorkerData,
2133
+ wrapRpc: () => wrapRpc
2134
+ });
2135
+
2136
+ // packages/dts-plugin/src/core/rpc/expose-rpc.ts
2137
+ var import_process = __toESM(require("process"));
2138
+
2139
+ // packages/dts-plugin/src/core/rpc/types.ts
2140
+ var RpcGMCallTypes = /* @__PURE__ */ ((RpcGMCallTypes2) => {
2141
+ RpcGMCallTypes2["CALL"] = "mf_call";
2142
+ RpcGMCallTypes2["RESOLVE"] = "mf_resolve";
2143
+ RpcGMCallTypes2["REJECT"] = "mf_reject";
2144
+ RpcGMCallTypes2["EXIT"] = "mf_exit";
2145
+ return RpcGMCallTypes2;
2146
+ })(RpcGMCallTypes || {});
2147
+
2148
+ // packages/dts-plugin/src/core/rpc/expose-rpc.ts
2149
+ function exposeRpc(fn) {
2150
+ const sendMessage = (message) => new Promise((resolve4, reject) => {
2151
+ if (!import_process.default.send) {
2152
+ reject(new Error(`Process ${import_process.default.pid} doesn't have IPC channels`));
2153
+ } else if (!import_process.default.connected) {
2154
+ reject(
2155
+ new Error(`Process ${import_process.default.pid} doesn't have open IPC channels`)
2156
+ );
2157
+ } else {
2158
+ import_process.default.send(message, void 0, void 0, (error2) => {
2159
+ if (error2) {
2160
+ reject(error2);
2161
+ } else {
2162
+ resolve4(void 0);
2163
+ }
2164
+ });
2165
+ }
2166
+ });
2167
+ const handleMessage = async (message) => {
2168
+ if (message.type === "mf_call" /* CALL */) {
2169
+ if (!import_process.default.send) {
2170
+ return;
2171
+ }
2172
+ let value, error2;
2173
+ try {
2174
+ value = await fn(...message.args);
2175
+ } catch (fnError) {
2176
+ error2 = fnError;
2177
+ }
2178
+ try {
2179
+ if (error2) {
2180
+ await sendMessage({
2181
+ type: "mf_reject" /* REJECT */,
2182
+ id: message.id,
2183
+ error: error2
2184
+ });
2185
+ } else {
2186
+ await sendMessage({
2187
+ type: "mf_resolve" /* RESOLVE */,
2188
+ id: message.id,
2189
+ value
2190
+ });
2191
+ }
2192
+ } catch (sendError) {
2193
+ if (error2) {
2194
+ if (error2 instanceof Error) {
2195
+ console.error(error2);
2196
+ }
2197
+ }
2198
+ console.error(sendError);
2199
+ }
2200
+ }
2201
+ };
2202
+ import_process.default.on("message", handleMessage);
2203
+ }
2204
+
2205
+ // packages/dts-plugin/src/core/rpc/rpc-error.ts
2206
+ var RpcExitError = class extends Error {
2207
+ constructor(message, code, signal) {
2208
+ super(message);
2209
+ this.code = code;
2210
+ this.signal = signal;
2211
+ this.name = "RpcExitError";
2239
2212
  }
2240
- _stopWhenSIGTERMOrSIGINT() {
2241
- process.on("SIGTERM", () => {
2242
- fileLog(
2243
- `Process(${process.pid}) SIGTERM, ModuleFederationDevServer will exit...`,
2244
- MF_SERVER_IDENTIFIER,
2245
- "warn"
2246
- );
2247
- this._exit();
2248
- });
2249
- process.on("SIGINT", () => {
2250
- fileLog(
2251
- `Process(${process.pid}) SIGINT, ModuleFederationDevServer will exit...`,
2252
- MF_SERVER_IDENTIFIER,
2253
- "warn"
2213
+ };
2214
+
2215
+ // packages/dts-plugin/src/core/rpc/wrap-rpc.ts
2216
+ function createControlledPromise() {
2217
+ let resolve4 = () => void 0;
2218
+ let reject = () => void 0;
2219
+ const promise = new Promise((aResolve, aReject) => {
2220
+ resolve4 = aResolve;
2221
+ reject = aReject;
2222
+ });
2223
+ return {
2224
+ promise,
2225
+ resolve: resolve4,
2226
+ reject
2227
+ };
2228
+ }
2229
+ function wrapRpc(childProcess, options) {
2230
+ return async (...args) => {
2231
+ if (!childProcess.send) {
2232
+ throw new Error(`Process ${childProcess.pid} doesn't have IPC channels`);
2233
+ } else if (!childProcess.connected) {
2234
+ throw new Error(
2235
+ `Process ${childProcess.pid} doesn't have open IPC channels`
2254
2236
  );
2255
- this._exit();
2256
- });
2257
- }
2258
- _handleUnexpectedExit() {
2259
- process.on("unhandledRejection", (error2) => {
2260
- if (this._isReconnecting) {
2261
- return;
2237
+ }
2238
+ const { id, once } = options;
2239
+ const {
2240
+ promise: resultPromise,
2241
+ resolve: resolveResult,
2242
+ reject: rejectResult
2243
+ } = createControlledPromise();
2244
+ const {
2245
+ promise: sendPromise,
2246
+ resolve: resolveSend,
2247
+ reject: rejectSend
2248
+ } = createControlledPromise();
2249
+ const handleMessage = (message) => {
2250
+ if ((message == null ? void 0 : message.id) === id) {
2251
+ if (message.type === "mf_resolve" /* RESOLVE */) {
2252
+ resolveResult(message.value);
2253
+ } else if (message.type === "mf_reject" /* REJECT */) {
2254
+ rejectResult(message.error);
2255
+ }
2262
2256
  }
2263
- console.error("Unhandled Rejection Error: ", error2);
2264
- fileLog(
2265
- `Process(${process.pid}) unhandledRejection, garfishModuleServer will exit...`,
2266
- MF_SERVER_IDENTIFIER,
2267
- "error"
2268
- );
2269
- this._exit();
2270
- });
2271
- process.on("uncaughtException", (error2) => {
2272
- if (this._isReconnecting) {
2273
- return;
2257
+ if (once && (childProcess == null ? void 0 : childProcess.kill)) {
2258
+ childProcess.kill("SIGTERM");
2274
2259
  }
2275
- console.error("Unhandled Exception Error: ", error2);
2276
- fileLog(
2277
- `Process(${process.pid}) uncaughtException, garfishModuleServer will exit...`,
2278
- MF_SERVER_IDENTIFIER,
2279
- "error"
2260
+ };
2261
+ const handleClose = (code, signal) => {
2262
+ rejectResult(
2263
+ new RpcExitError(
2264
+ code ? `Process ${childProcess.pid} exited with code ${code}${signal ? ` [${signal}]` : ""}` : `Process ${childProcess.pid} exited${signal ? ` [${signal}]` : ""}`,
2265
+ code,
2266
+ signal
2267
+ )
2280
2268
  );
2281
- this._exit();
2282
- });
2283
- }
2284
- _exit() {
2285
- this._reconnect = false;
2286
- if (this._publishWebSocket) {
2287
- const exitPublisher = new ExitPublisherAction({
2288
- name: this._name,
2289
- ip: this._ip
2290
- });
2291
- this._publishWebSocket.send(JSON.stringify(exitPublisher));
2292
- this._publishWebSocket.on("message", (message) => {
2293
- const parsedMessage = JSON.parse(
2294
- message.toString()
2295
- );
2296
- fileLog(
2297
- `[${parsedMessage.kind}]: ${JSON.stringify(parsedMessage)}`,
2298
- MF_SERVER_IDENTIFIER,
2299
- "info"
2300
- );
2301
- });
2302
- }
2303
- if (this._publishWebSocket) {
2304
- this._publishWebSocket.close();
2305
- this._publishWebSocket = null;
2306
- }
2307
- process.exit(0);
2308
- }
2309
- exit() {
2310
- this._exit();
2311
- }
2312
- update(options) {
2313
- if (!this._publishWebSocket || !this._isConnected) {
2314
- return;
2269
+ removeHandlers();
2270
+ };
2271
+ const removeHandlers = () => {
2272
+ childProcess.off("message", handleMessage);
2273
+ childProcess.off("close", handleClose);
2274
+ };
2275
+ if (once) {
2276
+ childProcess.once("message", handleMessage);
2277
+ } else {
2278
+ childProcess.on("message", handleMessage);
2315
2279
  }
2316
- const { updateKind, updateMode, updateSourcePaths } = options;
2317
- fileLog(
2318
- `update run, ${this._name} module update, updateKind: ${updateKind}, updateMode: ${updateMode}, updateSourcePaths: ${updateSourcePaths}`,
2319
- MF_SERVER_IDENTIFIER,
2320
- "info"
2280
+ childProcess.on("close", handleClose);
2281
+ childProcess.send(
2282
+ {
2283
+ type: "mf_call" /* CALL */,
2284
+ id,
2285
+ args
2286
+ },
2287
+ (error2) => {
2288
+ if (error2) {
2289
+ rejectSend(error2);
2290
+ removeHandlers();
2291
+ } else {
2292
+ resolveSend(void 0);
2293
+ }
2294
+ }
2321
2295
  );
2322
- if (updateKind === "RELOAD_PAGE" /* RELOAD_PAGE */) {
2323
- const notifyWebClient = new NotifyWebClientAction({
2324
- name: this._name,
2325
- updateMode
2326
- });
2327
- this._publishWebSocket.send(JSON.stringify(notifyWebClient));
2328
- return;
2329
- }
2330
- const updatePublisher = new UpdatePublisherAction({
2331
- name: this._name,
2332
- ip: this._ip,
2333
- updateMode,
2334
- updateKind,
2335
- updateSourcePaths: [this._name],
2336
- remoteTypeTarPath: this._remoteTypeTarPath
2337
- });
2338
- this._publishWebSocket.send(JSON.stringify(updatePublisher));
2339
- }
2340
- };
2296
+ return sendPromise.then(() => resultPromise);
2297
+ };
2298
+ }
2341
2299
 
2342
- // packages/dts-plugin/src/server/createKoaServer.ts
2343
- var import_fs_extra = __toESM(require("fs-extra"));
2344
- var import_koa = __toESM(require("koa"));
2345
- async function createKoaServer(options) {
2346
- const { typeTarPath } = options;
2347
- const freeport = await getFreePort();
2348
- const app = new import_koa.default();
2349
- app.use(async (ctx, next) => {
2350
- if (ctx.path === `/${DEFAULT_TAR_NAME}`) {
2351
- ctx.status = 200;
2352
- ctx.body = import_fs_extra.default.createReadStream(typeTarPath);
2353
- ctx.response.type = "application/x-gzip";
2354
- } else {
2355
- await next();
2300
+ // packages/dts-plugin/src/core/rpc/rpc-worker.ts
2301
+ var child_process = __toESM(require("child_process"));
2302
+ var process3 = __toESM(require("process"));
2303
+ var import_crypto = require("crypto");
2304
+ var FEDERATION_WORKER_DATA_ENV_KEY = "VMOK_WORKER_DATA_ENV";
2305
+ function createRpcWorker(modulePath, data, memoryLimit, once) {
2306
+ const options = {
2307
+ env: {
2308
+ ...process3.env,
2309
+ [FEDERATION_WORKER_DATA_ENV_KEY]: JSON.stringify(data || {})
2310
+ },
2311
+ stdio: ["inherit", "inherit", "inherit", "ipc"],
2312
+ serialization: "advanced"
2313
+ };
2314
+ if (memoryLimit) {
2315
+ options.execArgv = [`--max-old-space-size=${memoryLimit}`];
2316
+ }
2317
+ let childProcess, remoteMethod;
2318
+ const id = (0, import_crypto.randomUUID)();
2319
+ const worker = {
2320
+ connect(...args) {
2321
+ if (childProcess && !childProcess.connected) {
2322
+ childProcess.send({
2323
+ type: "mf_exit" /* EXIT */,
2324
+ id
2325
+ });
2326
+ childProcess = void 0;
2327
+ remoteMethod = void 0;
2328
+ }
2329
+ if (!(childProcess == null ? void 0 : childProcess.connected)) {
2330
+ childProcess = child_process.fork(modulePath, options);
2331
+ remoteMethod = wrapRpc(childProcess, { id, once });
2332
+ }
2333
+ if (!remoteMethod) {
2334
+ return Promise.reject(
2335
+ new Error("Worker is not connected - cannot perform RPC.")
2336
+ );
2337
+ }
2338
+ return remoteMethod(...args);
2339
+ },
2340
+ terminate() {
2341
+ var _a;
2342
+ (_a = childProcess == null ? void 0 : childProcess.send) == null ? void 0 : _a.call(childProcess, {
2343
+ type: "mf_exit" /* EXIT */,
2344
+ id
2345
+ });
2346
+ childProcess = void 0;
2347
+ remoteMethod = void 0;
2348
+ },
2349
+ get connected() {
2350
+ return Boolean(childProcess == null ? void 0 : childProcess.connected);
2351
+ },
2352
+ get process() {
2353
+ return childProcess;
2354
+ },
2355
+ get id() {
2356
+ return id;
2356
2357
  }
2357
- });
2358
- app.listen(freeport);
2359
- return {
2360
- server: app,
2361
- serverAddress: `http://${getIPV4()}:${freeport}`
2362
2358
  };
2359
+ return worker;
2360
+ }
2361
+ function getRpcWorkerData() {
2362
+ return JSON.parse(process3.env[FEDERATION_WORKER_DATA_ENV_KEY] || "{}");
2363
2363
  }
2364
2364
 
2365
2365
  // packages/dts-plugin/src/dev-worker/forkDevWorker.ts
2366
+ var import_sdk5 = require("@module-federation/sdk");
2366
2367
  var DEFAULT_LOCAL_IPS = ["localhost", "127.0.0.1"];
2367
2368
  function getIpFromEntry(entry) {
2368
2369
  let ip;