@le-space/ui 0.6.43 → 0.6.45
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/package.json +3 -3
- package/react/index.js +71 -3
- package/shared/index.d.ts +1 -1
- package/shared/index.js +71 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@le-space/ui",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.45",
|
|
4
4
|
"description": "Floating Aleph Relay Button UI components for Svelte and React.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"url": "https://github.com/NiKrause/relay-button/issues"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@le-space/browser": "0.6.
|
|
48
|
-
"@le-space/core": "0.6.
|
|
47
|
+
"@le-space/browser": "0.6.45",
|
|
48
|
+
"@le-space/core": "0.6.45",
|
|
49
49
|
"viem": "^2.53.1"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
package/react/index.js
CHANGED
|
@@ -43,7 +43,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
|
|
|
43
43
|
var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
|
|
44
44
|
|
|
45
45
|
// src/shared/package-version.ts
|
|
46
|
-
var UI_PACKAGE_VERSION = "0.6.
|
|
46
|
+
var UI_PACKAGE_VERSION = "0.6.45";
|
|
47
47
|
|
|
48
48
|
// src/shared/format.ts
|
|
49
49
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -3425,12 +3425,30 @@ async function waitForVmBootstrapConfigSignal(args) {
|
|
|
3425
3425
|
}).catch(() => []);
|
|
3426
3426
|
const match = signals.find((entry) => entry.status === expectedStatus) ?? null;
|
|
3427
3427
|
if (match) return match;
|
|
3428
|
+
if (args.shouldAbort && await args.shouldAbort().catch(() => false)) {
|
|
3429
|
+
return null;
|
|
3430
|
+
}
|
|
3428
3431
|
if (attempt < attempts - 1) {
|
|
3429
3432
|
await sleep2(delayMs);
|
|
3430
3433
|
}
|
|
3431
3434
|
}
|
|
3432
3435
|
return null;
|
|
3433
3436
|
}
|
|
3437
|
+
async function crnExecutionAbsent(args) {
|
|
3438
|
+
const base = String(args.crnUrl ?? "").trim();
|
|
3439
|
+
if (!base) return false;
|
|
3440
|
+
try {
|
|
3441
|
+
const response = await args.fetch(new URL("/about/executions/list", base).toString(), {
|
|
3442
|
+
cache: "no-store"
|
|
3443
|
+
});
|
|
3444
|
+
if (!response.ok) return false;
|
|
3445
|
+
const payload = await response.json();
|
|
3446
|
+
if (!payload || typeof payload !== "object") return false;
|
|
3447
|
+
return !(args.itemHash in payload);
|
|
3448
|
+
} catch {
|
|
3449
|
+
return false;
|
|
3450
|
+
}
|
|
3451
|
+
}
|
|
3434
3452
|
|
|
3435
3453
|
// ../core/src/bootstrap-reconcile.ts
|
|
3436
3454
|
function createRelayBootstrapRegistrationId(profile, instanceName, itemHash) {
|
|
@@ -4442,10 +4460,29 @@ var SponsorRelayController = class {
|
|
|
4442
4460
|
detail: "The relay received a 2n6 hostname, but it is not active yet. Waiting before handing HTTPS config to the guest."
|
|
4443
4461
|
});
|
|
4444
4462
|
let latestRuntime = runtime;
|
|
4463
|
+
let activationAbsentStreak = 0;
|
|
4445
4464
|
for (let attempt = 0; attempt < UI_RUNTIME_WAIT_ATTEMPTS; attempt += 1) {
|
|
4446
4465
|
if (latestRuntime.webAccess?.active === true) {
|
|
4447
4466
|
break;
|
|
4448
4467
|
}
|
|
4468
|
+
if (attempt > 0 && attempt % 6 === 0) {
|
|
4469
|
+
const absent = await crnExecutionAbsent({
|
|
4470
|
+
crnUrl: args.crnUrl,
|
|
4471
|
+
itemHash: args.itemHash,
|
|
4472
|
+
fetch: asJsonFetch
|
|
4473
|
+
});
|
|
4474
|
+
activationAbsentStreak = absent ? activationAbsentStreak + 1 : 0;
|
|
4475
|
+
if (activationAbsentStreak >= 4) {
|
|
4476
|
+
this.trace("deploy:crn-execution-absent-abort", {
|
|
4477
|
+
itemHash: args.itemHash,
|
|
4478
|
+
crnUrl: args.crnUrl ?? null,
|
|
4479
|
+
phase: "https-activation"
|
|
4480
|
+
});
|
|
4481
|
+
throw new Error(
|
|
4482
|
+
"The CRN never scheduled the relay VM (execution absent while waiting for HTTPS activation)."
|
|
4483
|
+
);
|
|
4484
|
+
}
|
|
4485
|
+
}
|
|
4449
4486
|
await new Promise(
|
|
4450
4487
|
(resolve) => globalThis.setTimeout(resolve, UI_RUNTIME_WAIT_DELAY_MS)
|
|
4451
4488
|
);
|
|
@@ -4552,7 +4589,37 @@ var SponsorRelayController = class {
|
|
|
4552
4589
|
// recovery path, which used to poll the guest over plain HTTP (mixed
|
|
4553
4590
|
// content on an HTTPS origin).
|
|
4554
4591
|
attempts: 100,
|
|
4555
|
-
delayMs: 3e3
|
|
4592
|
+
delayMs: 3e3,
|
|
4593
|
+
// Early failover (relay-button#83): a silently broken CRN accepts the
|
|
4594
|
+
// allocation but never schedules the VM. Probe the CRN's execution
|
|
4595
|
+
// list alongside the signal wait; after 4 consecutive "absent"
|
|
4596
|
+
// sightings (~2 min into the window) stop waiting — the full window
|
|
4597
|
+
// costs ~5 min and the VM will never publish a signal.
|
|
4598
|
+
shouldAbort: /* @__PURE__ */ (() => {
|
|
4599
|
+
let absentStreak = 0;
|
|
4600
|
+
let probeCountdown = 0;
|
|
4601
|
+
return async () => {
|
|
4602
|
+
if (probeCountdown > 0) {
|
|
4603
|
+
probeCountdown -= 1;
|
|
4604
|
+
return false;
|
|
4605
|
+
}
|
|
4606
|
+
probeCountdown = 9;
|
|
4607
|
+
const absent = await crnExecutionAbsent({
|
|
4608
|
+
crnUrl: args.crnUrl,
|
|
4609
|
+
itemHash: args.itemHash,
|
|
4610
|
+
fetch: asJsonFetch
|
|
4611
|
+
});
|
|
4612
|
+
absentStreak = absent ? absentStreak + 1 : 0;
|
|
4613
|
+
if (absentStreak >= 4) {
|
|
4614
|
+
this.trace("deploy:crn-execution-absent-abort", {
|
|
4615
|
+
itemHash: args.itemHash,
|
|
4616
|
+
crnUrl: args.crnUrl ?? null
|
|
4617
|
+
});
|
|
4618
|
+
return true;
|
|
4619
|
+
}
|
|
4620
|
+
return false;
|
|
4621
|
+
};
|
|
4622
|
+
})()
|
|
4556
4623
|
});
|
|
4557
4624
|
this.trace("deploy:bootstrap-config-signal-visible", {
|
|
4558
4625
|
itemHash: args.itemHash,
|
|
@@ -5738,7 +5805,8 @@ var SponsorRelayController = class {
|
|
|
5738
5805
|
await this.configureRelayBootstrapRegistration({
|
|
5739
5806
|
itemHash: result.itemHash,
|
|
5740
5807
|
runtime,
|
|
5741
|
-
deploymentToken: attemptDeploymentToken
|
|
5808
|
+
deploymentToken: attemptDeploymentToken,
|
|
5809
|
+
crnUrl: candidateCrn.address ?? null
|
|
5742
5810
|
});
|
|
5743
5811
|
this.patch({
|
|
5744
5812
|
busy: { deploying: false }
|
package/shared/index.d.ts
CHANGED
|
@@ -341,7 +341,7 @@ declare const STALE_INSTANCE_ALLOCATION_COOLDOWN_MS: number;
|
|
|
341
341
|
declare const RECENT_INSTANCE_RUNTIME_GRACE_MS: number;
|
|
342
342
|
declare const DEPLOYMENT_PENDING_WARNING_MS: number;
|
|
343
343
|
|
|
344
|
-
declare const UI_PACKAGE_VERSION = "0.6.
|
|
344
|
+
declare const UI_PACKAGE_VERSION = "0.6.45";
|
|
345
345
|
|
|
346
346
|
interface RootfsRequiredPortForward {
|
|
347
347
|
port: number;
|
package/shared/index.js
CHANGED
|
@@ -42,7 +42,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
|
|
|
42
42
|
var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
|
|
43
43
|
|
|
44
44
|
// src/shared/package-version.ts
|
|
45
|
-
var UI_PACKAGE_VERSION = "0.6.
|
|
45
|
+
var UI_PACKAGE_VERSION = "0.6.45";
|
|
46
46
|
|
|
47
47
|
// src/shared/format.ts
|
|
48
48
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -3424,12 +3424,30 @@ async function waitForVmBootstrapConfigSignal(args) {
|
|
|
3424
3424
|
}).catch(() => []);
|
|
3425
3425
|
const match = signals.find((entry) => entry.status === expectedStatus) ?? null;
|
|
3426
3426
|
if (match) return match;
|
|
3427
|
+
if (args.shouldAbort && await args.shouldAbort().catch(() => false)) {
|
|
3428
|
+
return null;
|
|
3429
|
+
}
|
|
3427
3430
|
if (attempt < attempts - 1) {
|
|
3428
3431
|
await sleep2(delayMs);
|
|
3429
3432
|
}
|
|
3430
3433
|
}
|
|
3431
3434
|
return null;
|
|
3432
3435
|
}
|
|
3436
|
+
async function crnExecutionAbsent(args) {
|
|
3437
|
+
const base = String(args.crnUrl ?? "").trim();
|
|
3438
|
+
if (!base) return false;
|
|
3439
|
+
try {
|
|
3440
|
+
const response = await args.fetch(new URL("/about/executions/list", base).toString(), {
|
|
3441
|
+
cache: "no-store"
|
|
3442
|
+
});
|
|
3443
|
+
if (!response.ok) return false;
|
|
3444
|
+
const payload = await response.json();
|
|
3445
|
+
if (!payload || typeof payload !== "object") return false;
|
|
3446
|
+
return !(args.itemHash in payload);
|
|
3447
|
+
} catch {
|
|
3448
|
+
return false;
|
|
3449
|
+
}
|
|
3450
|
+
}
|
|
3433
3451
|
|
|
3434
3452
|
// ../core/src/bootstrap-reconcile.ts
|
|
3435
3453
|
function createRelayBootstrapRegistrationId(profile, instanceName, itemHash) {
|
|
@@ -4441,10 +4459,29 @@ var SponsorRelayController = class {
|
|
|
4441
4459
|
detail: "The relay received a 2n6 hostname, but it is not active yet. Waiting before handing HTTPS config to the guest."
|
|
4442
4460
|
});
|
|
4443
4461
|
let latestRuntime = runtime;
|
|
4462
|
+
let activationAbsentStreak = 0;
|
|
4444
4463
|
for (let attempt = 0; attempt < UI_RUNTIME_WAIT_ATTEMPTS; attempt += 1) {
|
|
4445
4464
|
if (latestRuntime.webAccess?.active === true) {
|
|
4446
4465
|
break;
|
|
4447
4466
|
}
|
|
4467
|
+
if (attempt > 0 && attempt % 6 === 0) {
|
|
4468
|
+
const absent = await crnExecutionAbsent({
|
|
4469
|
+
crnUrl: args.crnUrl,
|
|
4470
|
+
itemHash: args.itemHash,
|
|
4471
|
+
fetch: asJsonFetch
|
|
4472
|
+
});
|
|
4473
|
+
activationAbsentStreak = absent ? activationAbsentStreak + 1 : 0;
|
|
4474
|
+
if (activationAbsentStreak >= 4) {
|
|
4475
|
+
this.trace("deploy:crn-execution-absent-abort", {
|
|
4476
|
+
itemHash: args.itemHash,
|
|
4477
|
+
crnUrl: args.crnUrl ?? null,
|
|
4478
|
+
phase: "https-activation"
|
|
4479
|
+
});
|
|
4480
|
+
throw new Error(
|
|
4481
|
+
"The CRN never scheduled the relay VM (execution absent while waiting for HTTPS activation)."
|
|
4482
|
+
);
|
|
4483
|
+
}
|
|
4484
|
+
}
|
|
4448
4485
|
await new Promise(
|
|
4449
4486
|
(resolve) => globalThis.setTimeout(resolve, UI_RUNTIME_WAIT_DELAY_MS)
|
|
4450
4487
|
);
|
|
@@ -4551,7 +4588,37 @@ var SponsorRelayController = class {
|
|
|
4551
4588
|
// recovery path, which used to poll the guest over plain HTTP (mixed
|
|
4552
4589
|
// content on an HTTPS origin).
|
|
4553
4590
|
attempts: 100,
|
|
4554
|
-
delayMs: 3e3
|
|
4591
|
+
delayMs: 3e3,
|
|
4592
|
+
// Early failover (relay-button#83): a silently broken CRN accepts the
|
|
4593
|
+
// allocation but never schedules the VM. Probe the CRN's execution
|
|
4594
|
+
// list alongside the signal wait; after 4 consecutive "absent"
|
|
4595
|
+
// sightings (~2 min into the window) stop waiting — the full window
|
|
4596
|
+
// costs ~5 min and the VM will never publish a signal.
|
|
4597
|
+
shouldAbort: /* @__PURE__ */ (() => {
|
|
4598
|
+
let absentStreak = 0;
|
|
4599
|
+
let probeCountdown = 0;
|
|
4600
|
+
return async () => {
|
|
4601
|
+
if (probeCountdown > 0) {
|
|
4602
|
+
probeCountdown -= 1;
|
|
4603
|
+
return false;
|
|
4604
|
+
}
|
|
4605
|
+
probeCountdown = 9;
|
|
4606
|
+
const absent = await crnExecutionAbsent({
|
|
4607
|
+
crnUrl: args.crnUrl,
|
|
4608
|
+
itemHash: args.itemHash,
|
|
4609
|
+
fetch: asJsonFetch
|
|
4610
|
+
});
|
|
4611
|
+
absentStreak = absent ? absentStreak + 1 : 0;
|
|
4612
|
+
if (absentStreak >= 4) {
|
|
4613
|
+
this.trace("deploy:crn-execution-absent-abort", {
|
|
4614
|
+
itemHash: args.itemHash,
|
|
4615
|
+
crnUrl: args.crnUrl ?? null
|
|
4616
|
+
});
|
|
4617
|
+
return true;
|
|
4618
|
+
}
|
|
4619
|
+
return false;
|
|
4620
|
+
};
|
|
4621
|
+
})()
|
|
4555
4622
|
});
|
|
4556
4623
|
this.trace("deploy:bootstrap-config-signal-visible", {
|
|
4557
4624
|
itemHash: args.itemHash,
|
|
@@ -5737,7 +5804,8 @@ var SponsorRelayController = class {
|
|
|
5737
5804
|
await this.configureRelayBootstrapRegistration({
|
|
5738
5805
|
itemHash: result.itemHash,
|
|
5739
5806
|
runtime,
|
|
5740
|
-
deploymentToken: attemptDeploymentToken
|
|
5807
|
+
deploymentToken: attemptDeploymentToken,
|
|
5808
|
+
crnUrl: candidateCrn.address ?? null
|
|
5741
5809
|
});
|
|
5742
5810
|
this.patch({
|
|
5743
5811
|
busy: { deploying: false }
|