@zixt/host 0.0.157 → 0.0.159

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.
Files changed (2) hide show
  1. package/dist/index.js +112 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ import { homedir as homedir6 } from "node:os";
28
28
  // package.json
29
29
  var package_default = {
30
30
  name: "@zixt/host",
31
- version: "0.0.157",
31
+ version: "0.0.159",
32
32
  type: "module",
33
33
  exports: {
34
34
  ".": "./src/client.ts",
@@ -20027,6 +20027,11 @@ var CLOSE_CODES = {
20027
20027
  revoked: 4004
20028
20028
  };
20029
20029
  var UNSUPPORTED_PROTOCOL_CLOSE_REASON = "unsupported protocol version";
20030
+ function parseUnsupportedProtocolCloseReason(detail) {
20031
+ if (detail === UNSUPPORTED_PROTOCOL_CLOSE_REASON) return { cloudProtocolVersion: null };
20032
+ const match = /^unsupported protocol version; cloud protocol (\d{1,6})$/.exec(detail);
20033
+ return match ? { cloudProtocolVersion: Number(match[1]) } : null;
20034
+ }
20030
20035
  var CLOSE_REASON_MAX_BYTES = 123;
20031
20036
 
20032
20037
  // ../../packages/contracts/src/webhook-automations.ts
@@ -26382,7 +26387,7 @@ var HostClient = class _HostClient {
26382
26387
  await this.unwindAllRuns("host connection was replaced by a newer client", "client_shutdown");
26383
26388
  return;
26384
26389
  }
26385
- const versionMismatch = code === CLOSE_CODES.protocolError && detail === UNSUPPORTED_PROTOCOL_CLOSE_REASON;
26390
+ const versionMismatch = code === CLOSE_CODES.protocolError && detail !== void 0 && parseUnsupportedProtocolCloseReason(detail) !== null;
26386
26391
  if (versionMismatch) {
26387
26392
  this.opts.onStatus?.("incompatible", detail);
26388
26393
  this.stopped = true;
@@ -30499,6 +30504,29 @@ function installedReleaseVersion(entry, root = versionsRoot()) {
30499
30504
  if (!version2 || !VERSION_DIR.test(version2)) return null;
30500
30505
  return resolve8(entry) === resolve8(installedReleaseEntry(version2, root)) ? version2 : null;
30501
30506
  }
30507
+ function compareReleaseVersions(left, right) {
30508
+ const parse4 = (version2) => version2.split(/[-+]/, 1)[0].split(".").map((part) => Number(part));
30509
+ const leftParts = parse4(left);
30510
+ const rightParts = parse4(right);
30511
+ for (let index = 0; index < 3; index += 1) {
30512
+ const difference = (leftParts[index] ?? 0) - (rightParts[index] ?? 0);
30513
+ if (difference !== 0) return difference;
30514
+ }
30515
+ return 0;
30516
+ }
30517
+ async function newestInstalledReleaseBelow(version2, excluded, root = versionsRoot()) {
30518
+ let names;
30519
+ try {
30520
+ names = await readdir6(root);
30521
+ } catch {
30522
+ return null;
30523
+ }
30524
+ const candidates = names.filter((name) => VERSION_DIR.test(name)).filter((name) => !excluded.has(name) && compareReleaseVersions(name, version2) < 0).sort(compareReleaseVersions).reverse();
30525
+ for (const candidate of candidates) {
30526
+ if (await validInstalledRelease(candidate, root)) return candidate;
30527
+ }
30528
+ return null;
30529
+ }
30502
30530
  function currentReleaseEntry(root = versionsRoot(), platform = process.platform) {
30503
30531
  return join12(root, platform === "win32" ? "current-launcher.cjs" : CURRENT_RELEASE_ENTRY);
30504
30532
  }
@@ -31472,6 +31500,15 @@ async function launchHostSupervisor(options = {}) {
31472
31500
  child = null;
31473
31501
  if (stopEscalation) clearTimeout(stopEscalation);
31474
31502
  stopEscalation = void 0;
31503
+ if (!stopping && ownershipDirectory !== null && !await access2(ownershipDirectory).then(
31504
+ () => true,
31505
+ () => false
31506
+ )) {
31507
+ log2(
31508
+ "Zixt Host launcher: another Zixt Host launcher took over this Machine; leaving it in charge"
31509
+ );
31510
+ return 0;
31511
+ }
31475
31512
  if (!await cleanupSupervisorBoundary(
31476
31513
  exited,
31477
31514
  childExited,
@@ -31603,6 +31640,7 @@ async function superviseHost(options = {}) {
31603
31640
  });
31604
31641
  const attempted = /* @__PURE__ */ new Set();
31605
31642
  let unsatisfiableUpdates = 0;
31643
+ const cloudRefusedVersions = /* @__PURE__ */ new Set();
31606
31644
  const waitOrShutdown = async (ms) => {
31607
31645
  if (shuttingDown2) return false;
31608
31646
  if (!customDelay) {
@@ -31683,6 +31721,14 @@ async function superviseHost(options = {}) {
31683
31721
  rollbackCandidate = null;
31684
31722
  }
31685
31723
  };
31724
+ const parkRefusedCandidate = async (version2) => {
31725
+ if (!releaseStore || releaseState?.candidateVersion !== version2) return;
31726
+ await releaseStore.clear();
31727
+ if (releaseState?.candidateVersion === version2) {
31728
+ releaseState = null;
31729
+ rollbackCandidate = null;
31730
+ }
31731
+ };
31686
31732
  const markReleaseValidated = async (version2) => {
31687
31733
  if (releaseState?.phase !== "probation" || releaseState.candidateVersion !== version2 || !releaseStore) {
31688
31734
  return;
@@ -31991,21 +32037,66 @@ async function superviseHost(options = {}) {
31991
32037
  const target = await published();
31992
32038
  let updateLanded = false;
31993
32039
  let rejectedUpdate = null;
32040
+ if (runtimeMs >= FAST_UPDATE_EXIT_MS) cloudRefusedVersions.clear();
31994
32041
  if (target === null) {
31995
32042
  log2(
31996
32043
  "Zixt Host: a newer release was reported but the registry is unreachable; staying on the current version"
31997
32044
  );
31998
32045
  } else if (target === command.version) {
32046
+ cloudRefusedVersions.add(target);
32047
+ await parkRefusedCandidate(target);
31999
32048
  if (unsatisfiableUpdates === 0) {
32000
32049
  log2(
32001
32050
  `Zixt Host: ${target} is the newest published Zixt Host, so no update can satisfy this cloud; the cloud this Machine is paired to speaks a newer Host protocol than any published release`
32002
32051
  );
32052
+ }
32053
+ const compatible = await newestInstalledReleaseBelow(target, cloudRefusedVersions);
32054
+ if (compatible) {
32055
+ log2(
32056
+ `Zixt Host: running installed ${compatible} while the cloud catches up with ${target}; this Machine returns to ${target} by itself once the cloud speaks its protocol`
32057
+ );
32058
+ command = {
32059
+ entry: installedReleaseEntry(compatible),
32060
+ version: compatible,
32061
+ // The parked newest release is not for this worker to re-request:
32062
+ // its own update checks skip it while the cloud stays behind.
32063
+ rejectedVersion: target
32064
+ };
32065
+ updateLanded = true;
32066
+ } else if (unsatisfiableUpdates === 0) {
32067
+ log2(
32068
+ "Zixt Host: no older installed release remains to serve this cloud; pair this Machine with a cloud running a published release, or start the Host from the same source checkout that cloud runs; this Machine connects by itself once a matching release is published"
32069
+ );
32070
+ }
32071
+ } else if (cloudRefusedVersions.has(target)) {
32072
+ if (command.version && runtimeMs < FAST_UPDATE_EXIT_MS) {
32073
+ cloudRefusedVersions.add(command.version);
32074
+ await parkRefusedCandidate(command.version);
32075
+ }
32076
+ const compatible = command.version ? await newestInstalledReleaseBelow(command.version, cloudRefusedVersions) : null;
32077
+ if (compatible) {
32078
+ log2(
32079
+ `Zixt Host: ${target} is still refused by the paired cloud; running installed ${compatible} until the cloud updates`
32080
+ );
32081
+ command = {
32082
+ entry: installedReleaseEntry(compatible),
32083
+ version: compatible,
32084
+ rejectedVersion: target
32085
+ };
32086
+ updateLanded = true;
32087
+ } else {
32003
32088
  log2(
32004
- "Zixt Host: pair this Machine with a cloud running a published release, or start the Host from the same source checkout that cloud runs; this Machine connects by itself once a matching release is published"
32089
+ `Zixt Host: the paired cloud refuses every installed release; waiting for the cloud or a newer published release`
32005
32090
  );
32006
32091
  }
32007
32092
  } else if (attempted.has(target)) {
32008
- log2(`Zixt Host: already running ${target}; ignoring a repeated update request`);
32093
+ if (command.version !== target && await validInstalledRelease(target)) {
32094
+ log2(`Zixt Host: returning to installed ${target} now that the cloud accepts it`);
32095
+ command = { entry: installedReleaseEntry(target), version: target };
32096
+ updateLanded = true;
32097
+ } else {
32098
+ log2(`Zixt Host: already running ${target}; ignoring a repeated update request`);
32099
+ }
32009
32100
  } else {
32010
32101
  let entry;
32011
32102
  const attempt = { failure: null };
@@ -44831,8 +44922,10 @@ var BrowserManager = class {
44831
44922
  }
44832
44923
  throw new Error("browser cookies changed too many times while synchronizing");
44833
44924
  });
44834
- const tracked = next.finally(() => {
44835
- if (this.cookieSyncTails.get(profileKey) === tracked) this.cookieSyncTails.delete(profileKey);
44925
+ const tracked = next.catch(() => {
44926
+ }).finally(() => {
44927
+ if (this.cookieSyncTails.get(profileKey) === tracked)
44928
+ this.cookieSyncTails.delete(profileKey);
44836
44929
  });
44837
44930
  this.cookieSyncTails.set(profileKey, tracked);
44838
44931
  return next;
@@ -48702,14 +48795,21 @@ var client = new HostClient({
48702
48795
  });
48703
48796
  queueMicrotask(() => shutdown(DO_NOT_RESTART_EXIT_CODE));
48704
48797
  break;
48705
- case "incompatible":
48706
- log.error("Zixt Cloud refused this Host as too old to connect", {
48707
- ...connectionContext,
48708
- protocol: PROTOCOL_VERSION,
48709
- next: packagedBuild ? "Zixt checks the published release now; nothing to do on this Machine" : "Update this checkout through Git and restart the Host"
48710
- });
48798
+ case "incompatible": {
48799
+ const refusal = detail ? parseUnsupportedProtocolCloseReason(detail) : null;
48800
+ const cloudBehind = refusal?.cloudProtocolVersion != null && refusal.cloudProtocolVersion < PROTOCOL_VERSION;
48801
+ log.error(
48802
+ cloudBehind ? "Zixt Cloud is behind this Host and refused the connection" : "Zixt Cloud refused this Host as too old to connect",
48803
+ {
48804
+ ...connectionContext,
48805
+ protocol: PROTOCOL_VERSION,
48806
+ ...refusal?.cloudProtocolVersion != null ? { cloudProtocol: refusal.cloudProtocolVersion } : {},
48807
+ next: packagedBuild ? cloudBehind ? "Zixt runs the newest installed release this cloud accepts until the cloud updates" : "Zixt checks the published release now; nothing to do on this Machine" : cloudBehind ? "Deploy the paired cloud, or run this checkout at the revision that cloud runs" : "Update this checkout through Git and restart the Host"
48808
+ }
48809
+ );
48711
48810
  queueMicrotask(() => shutdown(packagedBuild ? UPDATE_EXIT_CODE : DO_NOT_RESTART_EXIT_CODE));
48712
48811
  break;
48812
+ }
48713
48813
  case "rejected":
48714
48814
  log.error("Zixt Cloud refused this Machine", {
48715
48815
  ...connectionContext,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zixt/host",
3
- "version": "0.0.157",
3
+ "version": "0.0.159",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",