@forgeax/engine-host 0.1.27 → 0.1.29

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.
package/dist/index.mjs CHANGED
@@ -350,6 +350,30 @@ function modulesFromCatalog(catalog, realm, version = "static") {
350
350
  ...record.digest === void 0 ? {} : { digest: record.digest }
351
351
  }));
352
352
  }
353
+ async function createHostStartup(options = {}) {
354
+ const context = options.context ?? new Context();
355
+ const ownedContext = options.context === void 0;
356
+ const fibers = [];
357
+ let disposed = false;
358
+ try {
359
+ for (const plugin of options.startupPlugins ?? []) fibers.push(await context.plugin(plugin));
360
+ } catch (error) {
361
+ for (const fiber of fibers.reverse()) await fiber.dispose();
362
+ if (ownedContext) await context.fiber.dispose();
363
+ throw error;
364
+ }
365
+ return {
366
+ context,
367
+ ownedContext,
368
+ fibers,
369
+ async dispose() {
370
+ if (disposed) return;
371
+ disposed = true;
372
+ for (const fiber of [...fibers].reverse()) await fiber.dispose();
373
+ if (ownedContext) await context.fiber.dispose();
374
+ }
375
+ };
376
+ }
353
377
 
354
378
  // src/transport.ts
355
379
  var HOST_ASSEMBLY_SERVICE = "host/assembly.get";
@@ -650,8 +674,10 @@ function errorFromSummary(service, summary) {
650
674
  );
651
675
  }
652
676
  return new HostAssemblyError("host-transport-failure", summary.expected, summary.hint, {
677
+ ...detail,
653
678
  service,
654
- reason: summary.detail.reason ? String(summary.detail.reason) : summary.code
679
+ reason: summary.detail.reason ? String(summary.detail.reason) : summary.code,
680
+ remoteCode: summary.code
655
681
  });
656
682
  }
657
683
  function transportFailure(service, reason) {
@@ -973,7 +999,6 @@ function assertBackendCatalogIdentity(catalog, modules) {
973
999
  }
974
1000
  async function createBackendHost(options = {}) {
975
1001
  const context = options.context ?? new Context();
976
- const ownedContext = options.context === void 0;
977
1002
  const realm = options.realm ?? "engine";
978
1003
  const catalog = options.catalog;
979
1004
  const pairedBackendEntries = options.pairs?.flatMap((pair) => pair.backend === void 0 ? [] : [pair.backend.entry]) ?? [];
@@ -989,27 +1014,31 @@ async function createBackendHost(options = {}) {
989
1014
  });
990
1015
  const checkedInitial = validateHostAssembly(initialAssembly);
991
1016
  if (!checkedInitial.ok) {
992
- if (ownedContext) await context.fiber.dispose();
1017
+ if (options.context === void 0) await context.fiber.dispose();
993
1018
  throw checkedInitial.error;
994
1019
  }
995
1020
  const backendModules = options.pairs === void 0 ? modules : options.pairs.flatMap((pair) => pair.backend === void 0 ? [] : [pair.backend.module]);
996
1021
  assertBackendCatalogIdentity(catalog, backendModules);
997
1022
  const authority = authorityOf(checkedInitial.value);
998
1023
  const assembly = authority.authority;
999
- const bootstrapRevision = checkedInitial.value.revision;
1024
+ let bootstrapRevision = checkedInitial.value.revision;
1025
+ const activationListeners = /* @__PURE__ */ new Set();
1000
1026
  const transport = options.transport ?? createHostTransport();
1001
- let foundationFiber;
1027
+ let startup;
1002
1028
  let loaderFiber;
1003
1029
  let loader;
1004
1030
  let backendEntries = options.pairs === void 0 ? options.entries ?? options.assembly?.entries ?? [] : pairedBackendEntries;
1005
- const startupFibers = [];
1006
1031
  let unregisterAssemblyService;
1007
1032
  let unregisterActivationService;
1008
1033
  let unsubscribeAssembly;
1009
1034
  try {
1010
- foundationFiber = await context.plugin(hostFoundationPlugin(assembly, transport));
1011
- for (const plugin of options.startupPlugins ?? [])
1012
- startupFibers.push(await context.plugin(plugin));
1035
+ startup = await createHostStartup({
1036
+ context,
1037
+ startupPlugins: [
1038
+ hostFoundationPlugin(assembly, transport),
1039
+ ...options.startupPlugins ?? []
1040
+ ]
1041
+ });
1013
1042
  if (catalog !== void 0) {
1014
1043
  const bootstrapped = await bootstrapCatalogLoader(context, catalog, realm, {
1015
1044
  catalogDigest: checkedInitial.value.revision,
@@ -1037,6 +1066,7 @@ async function createBackendHost(options = {}) {
1037
1066
  );
1038
1067
  }
1039
1068
  await options.onActivationReport?.(report);
1069
+ for (const listener of activationListeners) await listener(report);
1040
1070
  return { accepted: true };
1041
1071
  }
1042
1072
  );
@@ -1048,9 +1078,7 @@ async function createBackendHost(options = {}) {
1048
1078
  unregisterAssemblyService?.();
1049
1079
  unsubscribeAssembly?.();
1050
1080
  await loaderFiber?.dispose();
1051
- for (const fiber of startupFibers.reverse()) await fiber.dispose();
1052
- await foundationFiber?.dispose();
1053
- if (ownedContext) await context.fiber.dispose();
1081
+ await startup?.dispose();
1054
1082
  throw error;
1055
1083
  }
1056
1084
  let disposed = false;
@@ -1059,8 +1087,22 @@ async function createBackendHost(options = {}) {
1059
1087
  ...loader === void 0 ? {} : { loader },
1060
1088
  assembly,
1061
1089
  transport,
1062
- ownedContext,
1063
- async update(nextInput) {
1090
+ ownedContext: options.context === void 0,
1091
+ subscribeActivationReports(listener) {
1092
+ if (disposed) {
1093
+ throw new HostAssemblyError(
1094
+ "host-assembly-service-unavailable",
1095
+ "the backend host to remain active while observing activation reports",
1096
+ "Subscribe on an active host instance.",
1097
+ { service: HOST_ACTIVATION_REPORT_SERVICE }
1098
+ );
1099
+ }
1100
+ activationListeners.add(listener);
1101
+ return () => {
1102
+ activationListeners.delete(listener);
1103
+ };
1104
+ },
1105
+ async update(nextInput, updateOptions) {
1064
1106
  if (disposed) {
1065
1107
  throw new HostAssemblyError(
1066
1108
  "host-assembly-service-unavailable",
@@ -1097,19 +1139,19 @@ async function createBackendHost(options = {}) {
1097
1139
  await loader.await();
1098
1140
  }
1099
1141
  backendEntries = nextBackendEntries;
1142
+ if (updateOptions?.bootstrap === true) bootstrapRevision = checkedCandidate.value.revision;
1100
1143
  return authority.publish(effectiveInput);
1101
1144
  },
1102
1145
  async dispose() {
1103
1146
  if (disposed) return;
1104
1147
  disposed = true;
1148
+ activationListeners.clear();
1105
1149
  unsubscribeAssembly?.();
1106
1150
  unregisterActivationService?.();
1107
1151
  unregisterAssemblyService?.();
1108
1152
  transport.close();
1109
1153
  await loaderFiber?.dispose();
1110
- for (const fiber of startupFibers.reverse()) await fiber.dispose();
1111
- await foundationFiber?.dispose();
1112
- if (ownedContext) await context.fiber.dispose();
1154
+ await startup?.dispose();
1113
1155
  }
1114
1156
  };
1115
1157
  return host;
@@ -1287,8 +1329,7 @@ async function createFrontendHost(options = {}) {
1287
1329
  return status;
1288
1330
  }
1289
1331
  };
1290
- const startupFibers = [];
1291
- let foundationFiber;
1332
+ let startup;
1292
1333
  let loaderFiber;
1293
1334
  let loader;
1294
1335
  let disposed = false;
@@ -1332,9 +1373,13 @@ async function createFrontendHost(options = {}) {
1332
1373
  });
1333
1374
  }
1334
1375
  try {
1335
- foundationFiber = await context.plugin(hostFoundationPlugin2(state, options.transport));
1336
- for (const plugin of options.startupPlugins ?? [])
1337
- startupFibers.push(await context.plugin(plugin));
1376
+ startup = await createHostStartup({
1377
+ context,
1378
+ startupPlugins: [
1379
+ hostFoundationPlugin2(state, options.transport),
1380
+ ...options.startupPlugins ?? []
1381
+ ]
1382
+ });
1338
1383
  if (options.autoActivate !== false) {
1339
1384
  const host2 = {
1340
1385
  context,
@@ -1370,9 +1415,7 @@ async function createFrontendHost(options = {}) {
1370
1415
  } catch (error) {
1371
1416
  removeTransportDisconnect?.();
1372
1417
  await loaderFiber?.dispose();
1373
- for (const fiber of startupFibers.reverse()) await fiber.dispose();
1374
- await foundationFiber?.dispose();
1375
- if (ownedContext) await context.fiber.dispose();
1418
+ await startup?.dispose();
1376
1419
  throw error;
1377
1420
  }
1378
1421
  const host = {
@@ -1410,9 +1453,7 @@ async function createFrontendHost(options = {}) {
1410
1453
  disposed = true;
1411
1454
  removeTransportDisconnect?.();
1412
1455
  await loaderFiber?.dispose();
1413
- for (const fiber of startupFibers.reverse()) await fiber.dispose();
1414
- await foundationFiber?.dispose();
1415
- if (ownedContext) await context.fiber.dispose();
1456
+ await startup?.dispose();
1416
1457
  status = { state: "disposed", revision: current.revision };
1417
1458
  }
1418
1459
  };
@@ -1468,6 +1509,6 @@ async function activateFrontendHost(host, next, options, realm, getLoader, setLo
1468
1509
  }
1469
1510
  }
1470
1511
 
1471
- export { HOST_ACTIVATION_REPORT_SERVICE, HOST_ASSEMBLY_CHANGED_TOPIC, HOST_ASSEMBLY_SCHEMA_VERSION, HOST_ASSEMBLY_SERVICE, HostAssemblyError, attachHostWebSocketServer, canonicalHostJson, connectHostWebSocket, createBackendHost, createFrontendHost, createHostAssembly, createHostTransport, createHostWebSocketClient, hostRevision, modulesFromCatalog, validateHostAssembly };
1512
+ export { HOST_ACTIVATION_REPORT_SERVICE, HOST_ASSEMBLY_CHANGED_TOPIC, HOST_ASSEMBLY_SCHEMA_VERSION, HOST_ASSEMBLY_SERVICE, HostAssemblyError, attachHostWebSocketServer, canonicalHostJson, connectHostWebSocket, createBackendHost, createFrontendHost, createHostAssembly, createHostStartup, createHostTransport, createHostWebSocketClient, hostRevision, modulesFromCatalog, validateHostAssembly };
1472
1513
  //# sourceMappingURL=index.mjs.map
1473
1514
  //# sourceMappingURL=index.mjs.map