@le-space/ui 0.6.37 → 0.6.39
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.d.ts +1 -0
- package/react/index.js +83 -5
- package/shared/index.d.ts +2 -1
- package/shared/index.js +83 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@le-space/ui",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.39",
|
|
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.39",
|
|
48
|
+
"@le-space/core": "0.6.39",
|
|
49
49
|
"viem": "^2.53.1"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
package/react/index.d.ts
CHANGED
|
@@ -346,6 +346,7 @@ declare class SponsorRelayController {
|
|
|
346
346
|
private patch;
|
|
347
347
|
private emitProgress;
|
|
348
348
|
private configureRelayBootstrapRegistration;
|
|
349
|
+
private probeRelayReachableOverProxy;
|
|
349
350
|
private cleanupStaleVmBootstrapConfigHistory;
|
|
350
351
|
private syncLatestDeploymentProgress;
|
|
351
352
|
private canSkipRuntimeRefresh;
|
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.39";
|
|
47
47
|
|
|
48
48
|
// src/shared/format.ts
|
|
49
49
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -4545,7 +4545,13 @@ var SponsorRelayController = class {
|
|
|
4545
4545
|
instanceItemHash: args.itemHash,
|
|
4546
4546
|
fetch: asJsonFetch,
|
|
4547
4547
|
apiHost: this.client.apiHost,
|
|
4548
|
-
|
|
4548
|
+
// The guest publishes this signal only after its describe step has a
|
|
4549
|
+
// browser-dialable address, which waits on AutoTLS for up to ~240 s.
|
|
4550
|
+
// Wait comfortably longer than that (100 × 3 s = 300 s) so the complete
|
|
4551
|
+
// signal arrives instead of timing out — a timeout here drops into the
|
|
4552
|
+
// recovery path, which used to poll the guest over plain HTTP (mixed
|
|
4553
|
+
// content on an HTTPS origin).
|
|
4554
|
+
attempts: 100,
|
|
4549
4555
|
delayMs: 3e3
|
|
4550
4556
|
});
|
|
4551
4557
|
this.trace("deploy:bootstrap-config-signal-visible", {
|
|
@@ -4597,6 +4603,12 @@ var SponsorRelayController = class {
|
|
|
4597
4603
|
browserBootstrapMultiaddrCount: relayMetadata.browserBootstrapMultiaddrs.length
|
|
4598
4604
|
});
|
|
4599
4605
|
} else {
|
|
4606
|
+
const canReadMetadataSecurely = profile === "uc-go-peer" && Boolean(runtime.proxyUrl);
|
|
4607
|
+
if (usesBootstrapConfigAggregate(this.state.manifest) && !canReadMetadataSecurely) {
|
|
4608
|
+
throw new Error(
|
|
4609
|
+
"The relay applied its bootstrap config but the acknowledgement did not carry its final multiaddrs, and this image exposes no HTTPS metadata endpoint. Reading them over plain HTTP would be blocked as mixed content on an HTTPS origin, so the deployment cannot be completed."
|
|
4610
|
+
);
|
|
4611
|
+
}
|
|
4600
4612
|
this.emitProgress({
|
|
4601
4613
|
stage: "publishing-bootstrap",
|
|
4602
4614
|
label: "Waiting for secure relay metadata",
|
|
@@ -4608,7 +4620,7 @@ var SponsorRelayController = class {
|
|
|
4608
4620
|
relayMetadata = await fetchRelayMetadataForRuntime({
|
|
4609
4621
|
runtime,
|
|
4610
4622
|
fetch: (url, init) => fetch(url, init),
|
|
4611
|
-
preferSecureMetadata:
|
|
4623
|
+
preferSecureMetadata: canReadMetadataSecurely,
|
|
4612
4624
|
attempts: 80,
|
|
4613
4625
|
delayMs: 3e3,
|
|
4614
4626
|
timeoutMs: 24e4,
|
|
@@ -4775,6 +4787,27 @@ var SponsorRelayController = class {
|
|
|
4775
4787
|
);
|
|
4776
4788
|
}
|
|
4777
4789
|
}
|
|
4790
|
+
if (profile === "orbitdb-relay") {
|
|
4791
|
+
const proxyHostname = (() => {
|
|
4792
|
+
try {
|
|
4793
|
+
return runtime.proxyUrl ? new URL(runtime.proxyUrl).hostname : null;
|
|
4794
|
+
} catch {
|
|
4795
|
+
return null;
|
|
4796
|
+
}
|
|
4797
|
+
})();
|
|
4798
|
+
if (proxyHostname) {
|
|
4799
|
+
const reachable = await this.probeRelayReachableOverProxy({
|
|
4800
|
+
proxyHostname,
|
|
4801
|
+
peerId,
|
|
4802
|
+
itemHash: args.itemHash
|
|
4803
|
+
});
|
|
4804
|
+
if (!reachable) {
|
|
4805
|
+
throw new Error(
|
|
4806
|
+
`Relay ${peerId} never became reachable over its HTTPS proxy (https://${proxyHostname}/health) within the readiness window \u2014 the CRN's proxy is not forwarding to the relay. Failing this attempt so another host can be tried.`
|
|
4807
|
+
);
|
|
4808
|
+
}
|
|
4809
|
+
}
|
|
4810
|
+
}
|
|
4778
4811
|
if (profile === "uc-go-peer" && args.deploymentToken) {
|
|
4779
4812
|
let cleanupAggregateItemHash = null;
|
|
4780
4813
|
await deleteVmBootstrapConfig({
|
|
@@ -4808,6 +4841,49 @@ var SponsorRelayController = class {
|
|
|
4808
4841
|
});
|
|
4809
4842
|
}
|
|
4810
4843
|
}
|
|
4844
|
+
async probeRelayReachableOverProxy(args) {
|
|
4845
|
+
const healthUrl = `https://${args.proxyHostname}/health`;
|
|
4846
|
+
const attempts = 30;
|
|
4847
|
+
const delayMs = 4e3;
|
|
4848
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
4849
|
+
try {
|
|
4850
|
+
const abort = new AbortController();
|
|
4851
|
+
const timeout = globalThis.setTimeout(() => abort.abort(), 1e4);
|
|
4852
|
+
const response = await fetch(healthUrl, {
|
|
4853
|
+
cache: "no-cache",
|
|
4854
|
+
signal: abort.signal
|
|
4855
|
+
});
|
|
4856
|
+
globalThis.clearTimeout(timeout);
|
|
4857
|
+
if (response.ok) {
|
|
4858
|
+
const payload = await response.json().catch(() => null);
|
|
4859
|
+
if (typeof payload?.peerId === "string" && payload.peerId === args.peerId) {
|
|
4860
|
+
this.emitProgress({
|
|
4861
|
+
stage: "publishing-bootstrap",
|
|
4862
|
+
label: "Relay reachable over HTTPS",
|
|
4863
|
+
progress: 98,
|
|
4864
|
+
status: "success",
|
|
4865
|
+
itemHash: args.itemHash,
|
|
4866
|
+
detail: `Relay answered on ${healthUrl} with its peer id (attempt ${attempt}/${attempts}).`
|
|
4867
|
+
});
|
|
4868
|
+
return true;
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4871
|
+
} catch {
|
|
4872
|
+
}
|
|
4873
|
+
this.emitProgress({
|
|
4874
|
+
stage: "publishing-bootstrap",
|
|
4875
|
+
label: "Waiting for relay to be reachable",
|
|
4876
|
+
progress: 98,
|
|
4877
|
+
status: "warning",
|
|
4878
|
+
itemHash: args.itemHash,
|
|
4879
|
+
detail: `Relay not yet reachable over ${healthUrl} (attempt ${attempt}/${attempts}).`
|
|
4880
|
+
});
|
|
4881
|
+
if (attempt < attempts) {
|
|
4882
|
+
await new Promise((resolve) => globalThis.setTimeout(resolve, delayMs));
|
|
4883
|
+
}
|
|
4884
|
+
}
|
|
4885
|
+
return false;
|
|
4886
|
+
}
|
|
4811
4887
|
async cleanupStaleVmBootstrapConfigHistory(args) {
|
|
4812
4888
|
if (!this.state.wallet.address || !args.currentAggregateItemHash) {
|
|
4813
4889
|
return;
|
|
@@ -5710,11 +5786,13 @@ var SponsorRelayController = class {
|
|
|
5710
5786
|
crnListUrl: this.props.crnListUrl,
|
|
5711
5787
|
requirePublicGuestIpv6ForProxy: true
|
|
5712
5788
|
});
|
|
5713
|
-
|
|
5789
|
+
const canReconcileMetadataSecurely = attemptProfile === "uc-go-peer" && Boolean(latestRuntime.proxyUrl);
|
|
5790
|
+
const mayReadMetadata = canReconcileMetadataSecurely || !usesBootstrapConfigAggregate(this.state.manifest);
|
|
5791
|
+
if (latestRuntime.diagnostics?.state === "ready" && mayReadMetadata) {
|
|
5714
5792
|
const reconciledRelayMetadata = await fetchRelayMetadataForRuntime({
|
|
5715
5793
|
runtime: latestRuntime,
|
|
5716
5794
|
fetch: (url, init) => fetch(url, init),
|
|
5717
|
-
preferSecureMetadata:
|
|
5795
|
+
preferSecureMetadata: canReconcileMetadataSecurely,
|
|
5718
5796
|
attempts: 3,
|
|
5719
5797
|
delayMs: 1e3,
|
|
5720
5798
|
timeoutMs: 15e3
|
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.39";
|
|
345
345
|
|
|
346
346
|
interface RootfsRequiredPortForward {
|
|
347
347
|
port: number;
|
|
@@ -405,6 +405,7 @@ declare class SponsorRelayController {
|
|
|
405
405
|
private patch;
|
|
406
406
|
private emitProgress;
|
|
407
407
|
private configureRelayBootstrapRegistration;
|
|
408
|
+
private probeRelayReachableOverProxy;
|
|
408
409
|
private cleanupStaleVmBootstrapConfigHistory;
|
|
409
410
|
private syncLatestDeploymentProgress;
|
|
410
411
|
private canSkipRuntimeRefresh;
|
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.39";
|
|
46
46
|
|
|
47
47
|
// src/shared/format.ts
|
|
48
48
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -4544,7 +4544,13 @@ var SponsorRelayController = class {
|
|
|
4544
4544
|
instanceItemHash: args.itemHash,
|
|
4545
4545
|
fetch: asJsonFetch,
|
|
4546
4546
|
apiHost: this.client.apiHost,
|
|
4547
|
-
|
|
4547
|
+
// The guest publishes this signal only after its describe step has a
|
|
4548
|
+
// browser-dialable address, which waits on AutoTLS for up to ~240 s.
|
|
4549
|
+
// Wait comfortably longer than that (100 × 3 s = 300 s) so the complete
|
|
4550
|
+
// signal arrives instead of timing out — a timeout here drops into the
|
|
4551
|
+
// recovery path, which used to poll the guest over plain HTTP (mixed
|
|
4552
|
+
// content on an HTTPS origin).
|
|
4553
|
+
attempts: 100,
|
|
4548
4554
|
delayMs: 3e3
|
|
4549
4555
|
});
|
|
4550
4556
|
this.trace("deploy:bootstrap-config-signal-visible", {
|
|
@@ -4596,6 +4602,12 @@ var SponsorRelayController = class {
|
|
|
4596
4602
|
browserBootstrapMultiaddrCount: relayMetadata.browserBootstrapMultiaddrs.length
|
|
4597
4603
|
});
|
|
4598
4604
|
} else {
|
|
4605
|
+
const canReadMetadataSecurely = profile === "uc-go-peer" && Boolean(runtime.proxyUrl);
|
|
4606
|
+
if (usesBootstrapConfigAggregate(this.state.manifest) && !canReadMetadataSecurely) {
|
|
4607
|
+
throw new Error(
|
|
4608
|
+
"The relay applied its bootstrap config but the acknowledgement did not carry its final multiaddrs, and this image exposes no HTTPS metadata endpoint. Reading them over plain HTTP would be blocked as mixed content on an HTTPS origin, so the deployment cannot be completed."
|
|
4609
|
+
);
|
|
4610
|
+
}
|
|
4599
4611
|
this.emitProgress({
|
|
4600
4612
|
stage: "publishing-bootstrap",
|
|
4601
4613
|
label: "Waiting for secure relay metadata",
|
|
@@ -4607,7 +4619,7 @@ var SponsorRelayController = class {
|
|
|
4607
4619
|
relayMetadata = await fetchRelayMetadataForRuntime({
|
|
4608
4620
|
runtime,
|
|
4609
4621
|
fetch: (url, init) => fetch(url, init),
|
|
4610
|
-
preferSecureMetadata:
|
|
4622
|
+
preferSecureMetadata: canReadMetadataSecurely,
|
|
4611
4623
|
attempts: 80,
|
|
4612
4624
|
delayMs: 3e3,
|
|
4613
4625
|
timeoutMs: 24e4,
|
|
@@ -4774,6 +4786,27 @@ var SponsorRelayController = class {
|
|
|
4774
4786
|
);
|
|
4775
4787
|
}
|
|
4776
4788
|
}
|
|
4789
|
+
if (profile === "orbitdb-relay") {
|
|
4790
|
+
const proxyHostname = (() => {
|
|
4791
|
+
try {
|
|
4792
|
+
return runtime.proxyUrl ? new URL(runtime.proxyUrl).hostname : null;
|
|
4793
|
+
} catch {
|
|
4794
|
+
return null;
|
|
4795
|
+
}
|
|
4796
|
+
})();
|
|
4797
|
+
if (proxyHostname) {
|
|
4798
|
+
const reachable = await this.probeRelayReachableOverProxy({
|
|
4799
|
+
proxyHostname,
|
|
4800
|
+
peerId,
|
|
4801
|
+
itemHash: args.itemHash
|
|
4802
|
+
});
|
|
4803
|
+
if (!reachable) {
|
|
4804
|
+
throw new Error(
|
|
4805
|
+
`Relay ${peerId} never became reachable over its HTTPS proxy (https://${proxyHostname}/health) within the readiness window \u2014 the CRN's proxy is not forwarding to the relay. Failing this attempt so another host can be tried.`
|
|
4806
|
+
);
|
|
4807
|
+
}
|
|
4808
|
+
}
|
|
4809
|
+
}
|
|
4777
4810
|
if (profile === "uc-go-peer" && args.deploymentToken) {
|
|
4778
4811
|
let cleanupAggregateItemHash = null;
|
|
4779
4812
|
await deleteVmBootstrapConfig({
|
|
@@ -4807,6 +4840,49 @@ var SponsorRelayController = class {
|
|
|
4807
4840
|
});
|
|
4808
4841
|
}
|
|
4809
4842
|
}
|
|
4843
|
+
async probeRelayReachableOverProxy(args) {
|
|
4844
|
+
const healthUrl = `https://${args.proxyHostname}/health`;
|
|
4845
|
+
const attempts = 30;
|
|
4846
|
+
const delayMs = 4e3;
|
|
4847
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
4848
|
+
try {
|
|
4849
|
+
const abort = new AbortController();
|
|
4850
|
+
const timeout = globalThis.setTimeout(() => abort.abort(), 1e4);
|
|
4851
|
+
const response = await fetch(healthUrl, {
|
|
4852
|
+
cache: "no-cache",
|
|
4853
|
+
signal: abort.signal
|
|
4854
|
+
});
|
|
4855
|
+
globalThis.clearTimeout(timeout);
|
|
4856
|
+
if (response.ok) {
|
|
4857
|
+
const payload = await response.json().catch(() => null);
|
|
4858
|
+
if (typeof payload?.peerId === "string" && payload.peerId === args.peerId) {
|
|
4859
|
+
this.emitProgress({
|
|
4860
|
+
stage: "publishing-bootstrap",
|
|
4861
|
+
label: "Relay reachable over HTTPS",
|
|
4862
|
+
progress: 98,
|
|
4863
|
+
status: "success",
|
|
4864
|
+
itemHash: args.itemHash,
|
|
4865
|
+
detail: `Relay answered on ${healthUrl} with its peer id (attempt ${attempt}/${attempts}).`
|
|
4866
|
+
});
|
|
4867
|
+
return true;
|
|
4868
|
+
}
|
|
4869
|
+
}
|
|
4870
|
+
} catch {
|
|
4871
|
+
}
|
|
4872
|
+
this.emitProgress({
|
|
4873
|
+
stage: "publishing-bootstrap",
|
|
4874
|
+
label: "Waiting for relay to be reachable",
|
|
4875
|
+
progress: 98,
|
|
4876
|
+
status: "warning",
|
|
4877
|
+
itemHash: args.itemHash,
|
|
4878
|
+
detail: `Relay not yet reachable over ${healthUrl} (attempt ${attempt}/${attempts}).`
|
|
4879
|
+
});
|
|
4880
|
+
if (attempt < attempts) {
|
|
4881
|
+
await new Promise((resolve) => globalThis.setTimeout(resolve, delayMs));
|
|
4882
|
+
}
|
|
4883
|
+
}
|
|
4884
|
+
return false;
|
|
4885
|
+
}
|
|
4810
4886
|
async cleanupStaleVmBootstrapConfigHistory(args) {
|
|
4811
4887
|
if (!this.state.wallet.address || !args.currentAggregateItemHash) {
|
|
4812
4888
|
return;
|
|
@@ -5709,11 +5785,13 @@ var SponsorRelayController = class {
|
|
|
5709
5785
|
crnListUrl: this.props.crnListUrl,
|
|
5710
5786
|
requirePublicGuestIpv6ForProxy: true
|
|
5711
5787
|
});
|
|
5712
|
-
|
|
5788
|
+
const canReconcileMetadataSecurely = attemptProfile === "uc-go-peer" && Boolean(latestRuntime.proxyUrl);
|
|
5789
|
+
const mayReadMetadata = canReconcileMetadataSecurely || !usesBootstrapConfigAggregate(this.state.manifest);
|
|
5790
|
+
if (latestRuntime.diagnostics?.state === "ready" && mayReadMetadata) {
|
|
5713
5791
|
const reconciledRelayMetadata = await fetchRelayMetadataForRuntime({
|
|
5714
5792
|
runtime: latestRuntime,
|
|
5715
5793
|
fetch: (url, init) => fetch(url, init),
|
|
5716
|
-
preferSecureMetadata:
|
|
5794
|
+
preferSecureMetadata: canReconcileMetadataSecurely,
|
|
5717
5795
|
attempts: 3,
|
|
5718
5796
|
delayMs: 1e3,
|
|
5719
5797
|
timeoutMs: 15e3
|