@le-space/ui 0.6.1 → 0.6.2
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 +14 -0
- package/react/index.js +699 -52
- package/shared/index.d.ts +16 -2
- package/shared/index.js +509 -37
- package/svelte/SponsorRelayFab.svelte +83 -12
package/shared/index.js
CHANGED
|
@@ -27,7 +27,7 @@ var RECENT_INSTANCE_RUNTIME_GRACE_MS = 10 * 60 * 1e3;
|
|
|
27
27
|
var DEPLOYMENT_PENDING_WARNING_MS = 3 * 60 * 1e3;
|
|
28
28
|
|
|
29
29
|
// src/shared/package-version.ts
|
|
30
|
-
var UI_PACKAGE_VERSION = "0.6.
|
|
30
|
+
var UI_PACKAGE_VERSION = "0.6.2";
|
|
31
31
|
|
|
32
32
|
// src/shared/format.ts
|
|
33
33
|
function shortHash(value, head = 8, tail = 6) {
|
|
@@ -2273,6 +2273,45 @@ async function configureOrbitdbRelaySetup2(args) {
|
|
|
2273
2273
|
clearTimeout(timeout);
|
|
2274
2274
|
}
|
|
2275
2275
|
}
|
|
2276
|
+
async function configureUcanStore(args) {
|
|
2277
|
+
const controller = new AbortController();
|
|
2278
|
+
const timeout = setTimeout(
|
|
2279
|
+
() => controller.abort(),
|
|
2280
|
+
Number(args.timeoutMs ?? 18e4)
|
|
2281
|
+
);
|
|
2282
|
+
const payload = {
|
|
2283
|
+
public_ipv4: args.hostIpv4,
|
|
2284
|
+
public_ipv6: args.publicIpv6 ?? void 0,
|
|
2285
|
+
proxy_url: args.proxyUrl ?? void 0,
|
|
2286
|
+
webauthn_origin: args.webauthnOrigin ?? void 0,
|
|
2287
|
+
webauthn_origin_fallbacks: args.webauthnOriginFallbacks ?? void 0,
|
|
2288
|
+
admin_did: args.adminDid ?? void 0,
|
|
2289
|
+
bootstrap_package: args.bootstrapPackage ?? void 0,
|
|
2290
|
+
no_start: args.noStart === true ? true : void 0
|
|
2291
|
+
};
|
|
2292
|
+
try {
|
|
2293
|
+
const response = await args.fetch(
|
|
2294
|
+
`http://${args.hostIpv4}:${args.setupPort}/configure`,
|
|
2295
|
+
{
|
|
2296
|
+
method: "POST",
|
|
2297
|
+
headers: {
|
|
2298
|
+
"content-type": "application/json"
|
|
2299
|
+
},
|
|
2300
|
+
body: JSON.stringify(payload),
|
|
2301
|
+
signal: controller.signal
|
|
2302
|
+
}
|
|
2303
|
+
);
|
|
2304
|
+
const responsePayload = await response.json().catch(() => null);
|
|
2305
|
+
if (!response.ok) {
|
|
2306
|
+
throw new Error(
|
|
2307
|
+
`Service setup request failed: ${response.status} ${typeof responsePayload === "string" ? responsePayload : JSON.stringify(responsePayload ?? {})}`
|
|
2308
|
+
);
|
|
2309
|
+
}
|
|
2310
|
+
return responsePayload;
|
|
2311
|
+
} finally {
|
|
2312
|
+
clearTimeout(timeout);
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2276
2315
|
async function fetchUcGoPeerMetadata(args) {
|
|
2277
2316
|
const attempts = Math.max(1, Number(args.attempts ?? 60));
|
|
2278
2317
|
const delayMs = Math.max(0, Number(args.delayMs ?? 3e3));
|
|
@@ -2340,7 +2379,7 @@ async function fetchUcGoPeerMetadata(args) {
|
|
|
2340
2379
|
}
|
|
2341
2380
|
}
|
|
2342
2381
|
throw new Error(
|
|
2343
|
-
`
|
|
2382
|
+
`Guest metadata did not become ready after ${attempts} attempts: ${lastError ? lastError : typeof lastPayload === "string" ? lastPayload : JSON.stringify(lastPayload ?? {})}`
|
|
2344
2383
|
);
|
|
2345
2384
|
}
|
|
2346
2385
|
|
|
@@ -3272,7 +3311,130 @@ function createDeploymentProgressEmitter() {
|
|
|
3272
3311
|
};
|
|
3273
3312
|
}
|
|
3274
3313
|
|
|
3314
|
+
// ../shared-types/src/ucan-store-bootstrap.ts
|
|
3315
|
+
function isRecord(value) {
|
|
3316
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3317
|
+
}
|
|
3318
|
+
function normalizeNonEmptyString(value) {
|
|
3319
|
+
if (typeof value !== "string") return null;
|
|
3320
|
+
const normalized = value.trim();
|
|
3321
|
+
return normalized ? normalized : null;
|
|
3322
|
+
}
|
|
3323
|
+
function normalizeDid(value) {
|
|
3324
|
+
const did = normalizeNonEmptyString(value);
|
|
3325
|
+
return did && did.startsWith("did:") ? did : null;
|
|
3326
|
+
}
|
|
3327
|
+
function normalizeOrigin(value) {
|
|
3328
|
+
const raw = normalizeNonEmptyString(value);
|
|
3329
|
+
if (!raw) return null;
|
|
3330
|
+
try {
|
|
3331
|
+
const parsed = new URL(raw);
|
|
3332
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || !parsed.hostname || parsed.pathname && parsed.pathname !== "/" || parsed.search || parsed.hash) {
|
|
3333
|
+
return null;
|
|
3334
|
+
}
|
|
3335
|
+
return parsed.origin;
|
|
3336
|
+
} catch {
|
|
3337
|
+
return null;
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
function normalizeExpiration(value) {
|
|
3341
|
+
if (value == null) return void 0;
|
|
3342
|
+
if (value === null) return null;
|
|
3343
|
+
if (!Number.isInteger(value) || Number(value) < 0) return void 0;
|
|
3344
|
+
return Number(value);
|
|
3345
|
+
}
|
|
3346
|
+
function validateUcanStoreBootstrapPackage(value) {
|
|
3347
|
+
if (!isRecord(value)) {
|
|
3348
|
+
return {
|
|
3349
|
+
valid: false,
|
|
3350
|
+
errors: ["Bootstrap package must be a JSON object."],
|
|
3351
|
+
bootstrapPackage: null
|
|
3352
|
+
};
|
|
3353
|
+
}
|
|
3354
|
+
const errors = [];
|
|
3355
|
+
const operatorAddress = normalizeNonEmptyString(value.operatorAddress);
|
|
3356
|
+
if (!operatorAddress || !/^0x[a-fA-F0-9]{40}$/.test(operatorAddress)) {
|
|
3357
|
+
errors.push("operatorAddress must be a 0x-prefixed 20-byte Ethereum address.");
|
|
3358
|
+
}
|
|
3359
|
+
const adminDid = normalizeDid(value.adminDid);
|
|
3360
|
+
if (!adminDid) {
|
|
3361
|
+
errors.push("adminDid must be a non-empty DID string.");
|
|
3362
|
+
}
|
|
3363
|
+
const serviceDidRaw = value.serviceDid;
|
|
3364
|
+
const serviceDid = serviceDidRaw == null || serviceDidRaw === "" ? null : normalizeDid(serviceDidRaw);
|
|
3365
|
+
if (serviceDidRaw != null && serviceDidRaw !== "" && !serviceDid) {
|
|
3366
|
+
errors.push("serviceDid must be empty or a non-empty DID string.");
|
|
3367
|
+
}
|
|
3368
|
+
const spaceDid = normalizeDid(value.spaceDid);
|
|
3369
|
+
if (!spaceDid) {
|
|
3370
|
+
errors.push("spaceDid must be a non-empty DID string.");
|
|
3371
|
+
}
|
|
3372
|
+
const rootDelegationProof = normalizeNonEmptyString(value.rootDelegationProof);
|
|
3373
|
+
if (!rootDelegationProof) {
|
|
3374
|
+
errors.push("rootDelegationProof must be a non-empty proof string.");
|
|
3375
|
+
}
|
|
3376
|
+
const allowedCapabilities = Array.isArray(value.allowedCapabilities) ? value.allowedCapabilities.map((entry) => normalizeNonEmptyString(entry)).filter((entry) => Boolean(entry)) : [];
|
|
3377
|
+
if (allowedCapabilities.length === 0) {
|
|
3378
|
+
errors.push("allowedCapabilities must contain at least one capability string.");
|
|
3379
|
+
}
|
|
3380
|
+
const defaultUserDelegationExpiration = normalizeExpiration(
|
|
3381
|
+
value.defaultUserDelegationExpiration
|
|
3382
|
+
);
|
|
3383
|
+
if (value.defaultUserDelegationExpiration != null && defaultUserDelegationExpiration === void 0) {
|
|
3384
|
+
errors.push(
|
|
3385
|
+
"defaultUserDelegationExpiration must be null or a non-negative integer number of seconds."
|
|
3386
|
+
);
|
|
3387
|
+
}
|
|
3388
|
+
const maxUserDelegationExpiration = normalizeExpiration(
|
|
3389
|
+
value.maxUserDelegationExpiration
|
|
3390
|
+
);
|
|
3391
|
+
if (value.maxUserDelegationExpiration != null && maxUserDelegationExpiration === void 0) {
|
|
3392
|
+
errors.push(
|
|
3393
|
+
"maxUserDelegationExpiration must be null or a non-negative integer number of seconds."
|
|
3394
|
+
);
|
|
3395
|
+
}
|
|
3396
|
+
if (typeof defaultUserDelegationExpiration === "number" && typeof maxUserDelegationExpiration === "number" && defaultUserDelegationExpiration > maxUserDelegationExpiration) {
|
|
3397
|
+
errors.push(
|
|
3398
|
+
"defaultUserDelegationExpiration cannot exceed maxUserDelegationExpiration."
|
|
3399
|
+
);
|
|
3400
|
+
}
|
|
3401
|
+
const pwaOrigin = normalizeOrigin(value.pwaOrigin);
|
|
3402
|
+
if (!pwaOrigin) {
|
|
3403
|
+
errors.push("pwaOrigin must be an http(s) origin without path, query, or hash.");
|
|
3404
|
+
}
|
|
3405
|
+
const serviceOrigin = normalizeOrigin(value.serviceOrigin);
|
|
3406
|
+
if (!serviceOrigin) {
|
|
3407
|
+
errors.push("serviceOrigin must be an http(s) origin without path, query, or hash.");
|
|
3408
|
+
}
|
|
3409
|
+
if (errors.length > 0) {
|
|
3410
|
+
return {
|
|
3411
|
+
valid: false,
|
|
3412
|
+
errors,
|
|
3413
|
+
bootstrapPackage: null
|
|
3414
|
+
};
|
|
3415
|
+
}
|
|
3416
|
+
return {
|
|
3417
|
+
valid: true,
|
|
3418
|
+
errors: [],
|
|
3419
|
+
bootstrapPackage: {
|
|
3420
|
+
operatorAddress,
|
|
3421
|
+
adminDid,
|
|
3422
|
+
serviceDid,
|
|
3423
|
+
spaceDid,
|
|
3424
|
+
rootDelegationProof,
|
|
3425
|
+
allowedCapabilities,
|
|
3426
|
+
defaultUserDelegationExpiration,
|
|
3427
|
+
maxUserDelegationExpiration,
|
|
3428
|
+
pwaOrigin,
|
|
3429
|
+
serviceOrigin
|
|
3430
|
+
}
|
|
3431
|
+
};
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3275
3434
|
// src/shared/controller.ts
|
|
3435
|
+
function deploymentNoun(profile) {
|
|
3436
|
+
return profile === "ucan-store" ? "service" : "relay";
|
|
3437
|
+
}
|
|
3276
3438
|
function asJsonFetch(input, init) {
|
|
3277
3439
|
return fetch(input, init).then(async (response) => ({
|
|
3278
3440
|
ok: response.ok,
|
|
@@ -3280,11 +3442,122 @@ function asJsonFetch(input, init) {
|
|
|
3280
3442
|
json: async () => await response.json()
|
|
3281
3443
|
}));
|
|
3282
3444
|
}
|
|
3283
|
-
function
|
|
3445
|
+
function isConfirmedGuestSetupResult(value) {
|
|
3284
3446
|
return Boolean(
|
|
3285
3447
|
value && typeof value === "object" && "status" in value && value.status === "configured"
|
|
3286
3448
|
);
|
|
3287
3449
|
}
|
|
3450
|
+
function defaultUcanStoreBootstrapInput(props) {
|
|
3451
|
+
return {
|
|
3452
|
+
adminDid: props.ucanStoreBootstrap?.adminDid ?? "",
|
|
3453
|
+
serviceDid: props.ucanStoreBootstrap?.serviceDid ?? "",
|
|
3454
|
+
spaceDid: props.ucanStoreBootstrap?.spaceDid ?? "",
|
|
3455
|
+
rootDelegationProof: props.ucanStoreBootstrap?.rootDelegationProof ?? "",
|
|
3456
|
+
allowedCapabilities: props.ucanStoreBootstrap?.allowedCapabilities ?? "",
|
|
3457
|
+
defaultUserDelegationExpiration: props.ucanStoreBootstrap?.defaultUserDelegationExpiration ?? "",
|
|
3458
|
+
maxUserDelegationExpiration: props.ucanStoreBootstrap?.maxUserDelegationExpiration ?? "",
|
|
3459
|
+
pwaOrigin: props.ucanStoreBootstrap?.pwaOrigin ?? "",
|
|
3460
|
+
serviceOrigin: props.ucanStoreBootstrap?.serviceOrigin ?? ""
|
|
3461
|
+
};
|
|
3462
|
+
}
|
|
3463
|
+
function currentPageOrigin() {
|
|
3464
|
+
try {
|
|
3465
|
+
const origin = globalThis.location?.origin?.trim();
|
|
3466
|
+
return origin ? origin : null;
|
|
3467
|
+
} catch {
|
|
3468
|
+
return null;
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
function parseOptionalExpiration(value) {
|
|
3472
|
+
const normalized = value.trim();
|
|
3473
|
+
if (!normalized) return void 0;
|
|
3474
|
+
const parsed = Number.parseInt(normalized, 10);
|
|
3475
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
3476
|
+
return null;
|
|
3477
|
+
}
|
|
3478
|
+
return parsed;
|
|
3479
|
+
}
|
|
3480
|
+
function parseAllowedCapabilities(value) {
|
|
3481
|
+
return value.split(/[\n,]/).map((entry) => entry.trim()).filter(Boolean);
|
|
3482
|
+
}
|
|
3483
|
+
function draftUcanStoreBootstrapErrors(args) {
|
|
3484
|
+
const errors = [];
|
|
3485
|
+
const { input } = args;
|
|
3486
|
+
if (!args.operatorAddress) {
|
|
3487
|
+
errors.push("Connect MetaMask before configuring the ucan-store bootstrap package.");
|
|
3488
|
+
}
|
|
3489
|
+
if (!input.adminDid.trim().startsWith("did:")) {
|
|
3490
|
+
errors.push("Admin DID must be a non-empty DID string.");
|
|
3491
|
+
}
|
|
3492
|
+
if (input.serviceDid.trim() && !input.serviceDid.trim().startsWith("did:")) {
|
|
3493
|
+
errors.push("Service DID must be empty or a non-empty DID string.");
|
|
3494
|
+
}
|
|
3495
|
+
if (!input.spaceDid.trim().startsWith("did:")) {
|
|
3496
|
+
errors.push("Space DID must be a non-empty DID string.");
|
|
3497
|
+
}
|
|
3498
|
+
if (!input.rootDelegationProof.trim()) {
|
|
3499
|
+
errors.push("Root delegation proof is required.");
|
|
3500
|
+
}
|
|
3501
|
+
if (parseAllowedCapabilities(input.allowedCapabilities).length === 0) {
|
|
3502
|
+
errors.push("Add at least one allowed capability.");
|
|
3503
|
+
}
|
|
3504
|
+
const defaultExpiration = parseOptionalExpiration(
|
|
3505
|
+
input.defaultUserDelegationExpiration
|
|
3506
|
+
);
|
|
3507
|
+
if (defaultExpiration === null) {
|
|
3508
|
+
errors.push(
|
|
3509
|
+
"Default user delegation expiration must be a non-negative integer number of seconds."
|
|
3510
|
+
);
|
|
3511
|
+
}
|
|
3512
|
+
const maxExpiration = parseOptionalExpiration(
|
|
3513
|
+
input.maxUserDelegationExpiration
|
|
3514
|
+
);
|
|
3515
|
+
if (maxExpiration === null) {
|
|
3516
|
+
errors.push(
|
|
3517
|
+
"Max user delegation expiration must be a non-negative integer number of seconds."
|
|
3518
|
+
);
|
|
3519
|
+
}
|
|
3520
|
+
if (typeof defaultExpiration === "number" && typeof maxExpiration === "number" && defaultExpiration > maxExpiration) {
|
|
3521
|
+
errors.push(
|
|
3522
|
+
"Default user delegation expiration cannot exceed the max user delegation expiration."
|
|
3523
|
+
);
|
|
3524
|
+
}
|
|
3525
|
+
const pwaOrigin = input.pwaOrigin.trim() || currentPageOrigin() || "";
|
|
3526
|
+
if (!pwaOrigin) {
|
|
3527
|
+
errors.push("PWA origin is required for the ucan-store bootstrap package.");
|
|
3528
|
+
}
|
|
3529
|
+
return errors;
|
|
3530
|
+
}
|
|
3531
|
+
function buildUcanStoreBootstrapPackage(args) {
|
|
3532
|
+
const candidate = {
|
|
3533
|
+
operatorAddress: args.operatorAddress,
|
|
3534
|
+
adminDid: args.input.adminDid.trim(),
|
|
3535
|
+
serviceDid: args.input.serviceDid.trim() || null,
|
|
3536
|
+
spaceDid: args.input.spaceDid.trim(),
|
|
3537
|
+
rootDelegationProof: args.input.rootDelegationProof.trim(),
|
|
3538
|
+
allowedCapabilities: parseAllowedCapabilities(args.input.allowedCapabilities),
|
|
3539
|
+
defaultUserDelegationExpiration: parseOptionalExpiration(
|
|
3540
|
+
args.input.defaultUserDelegationExpiration
|
|
3541
|
+
),
|
|
3542
|
+
maxUserDelegationExpiration: parseOptionalExpiration(
|
|
3543
|
+
args.input.maxUserDelegationExpiration
|
|
3544
|
+
),
|
|
3545
|
+
pwaOrigin: args.input.pwaOrigin.trim() || args.pwaOriginFallback?.trim() || currentPageOrigin() || "",
|
|
3546
|
+
serviceOrigin: args.input.serviceOrigin.trim() || args.serviceOriginFallback?.trim() || ""
|
|
3547
|
+
};
|
|
3548
|
+
if (candidate.defaultUserDelegationExpiration === void 0) {
|
|
3549
|
+
delete candidate.defaultUserDelegationExpiration;
|
|
3550
|
+
}
|
|
3551
|
+
if (candidate.maxUserDelegationExpiration === void 0) {
|
|
3552
|
+
delete candidate.maxUserDelegationExpiration;
|
|
3553
|
+
}
|
|
3554
|
+
if (candidate.serviceDid === null) {
|
|
3555
|
+
delete candidate.serviceDid;
|
|
3556
|
+
}
|
|
3557
|
+
return validateUcanStoreBootstrapPackage(
|
|
3558
|
+
candidate
|
|
3559
|
+
);
|
|
3560
|
+
}
|
|
3288
3561
|
function defaultState(props = {}) {
|
|
3289
3562
|
return {
|
|
3290
3563
|
ready: false,
|
|
@@ -3299,6 +3572,7 @@ function defaultState(props = {}) {
|
|
|
3299
3572
|
manifestJson: props.manifestJson ?? "",
|
|
3300
3573
|
sshPublicKey: props.sshPublicKey ?? "",
|
|
3301
3574
|
instanceName: props.instanceName ?? DEFAULT_INSTANCE_NAME,
|
|
3575
|
+
ucanStoreBootstrap: defaultUcanStoreBootstrapInput(props),
|
|
3302
3576
|
tierId: DEFAULT_TIER_ID,
|
|
3303
3577
|
showAdvanced: Boolean(props.manifestJson?.trim() || props.sshPublicKey?.trim()),
|
|
3304
3578
|
showInstances: props.showInstances ?? true,
|
|
@@ -3433,13 +3707,33 @@ async function resolveManifest(args) {
|
|
|
3433
3707
|
if (pasted) return pasted;
|
|
3434
3708
|
return loadRootfsManifest(args.manifestUrl);
|
|
3435
3709
|
}
|
|
3436
|
-
function
|
|
3710
|
+
function deploymentProfileForManifest(manifest) {
|
|
3437
3711
|
if (manifest?.profile === "uc-go-peer") return "uc-go-peer";
|
|
3438
3712
|
if (manifest?.profile === "orbitdb-relay") {
|
|
3439
3713
|
return manifest.profile;
|
|
3440
3714
|
}
|
|
3715
|
+
if (manifest?.profile === "ucan-store") return "ucan-store";
|
|
3716
|
+
return null;
|
|
3717
|
+
}
|
|
3718
|
+
function bootstrapRelayProfileForManifest(manifest) {
|
|
3719
|
+
const profile = deploymentProfileForManifest(manifest);
|
|
3720
|
+
if (profile === "uc-go-peer" || profile === "orbitdb-relay") {
|
|
3721
|
+
return profile;
|
|
3722
|
+
}
|
|
3441
3723
|
return null;
|
|
3442
3724
|
}
|
|
3725
|
+
function supportsBootstrapRegistrationsForManifest(manifest) {
|
|
3726
|
+
return bootstrapRelayProfileForManifest(manifest) != null;
|
|
3727
|
+
}
|
|
3728
|
+
function deploymentReadyLabel(profile) {
|
|
3729
|
+
return profile === "ucan-store" ? "Service ready" : "Relay ready";
|
|
3730
|
+
}
|
|
3731
|
+
function deploymentReadyDetail(profile, fallback) {
|
|
3732
|
+
if (profile === "ucan-store") {
|
|
3733
|
+
return "The upload service runtime is available and the deployment finished successfully.";
|
|
3734
|
+
}
|
|
3735
|
+
return fallback;
|
|
3736
|
+
}
|
|
3443
3737
|
function registrationIdInstanceItemHash(registrationId) {
|
|
3444
3738
|
const normalized = String(registrationId ?? "").trim();
|
|
3445
3739
|
if (!normalized) return null;
|
|
@@ -3688,19 +3982,148 @@ var SponsorRelayController = class {
|
|
|
3688
3982
|
this.progressEmitter.emit(nextEvent);
|
|
3689
3983
|
}
|
|
3690
3984
|
async configureRelayBootstrapRegistration(args) {
|
|
3691
|
-
const
|
|
3692
|
-
|
|
3693
|
-
if (!
|
|
3985
|
+
const deploymentProfile = deploymentProfileForManifest(this.state.manifest);
|
|
3986
|
+
const profile = bootstrapRelayProfileForManifest(this.state.manifest);
|
|
3987
|
+
if (!profile && deploymentProfile !== "ucan-store") return;
|
|
3988
|
+
if (profile && !this.state.wallet.address) {
|
|
3694
3989
|
throw new Error("A connected wallet is required to register relay bootstrap addresses.");
|
|
3695
3990
|
}
|
|
3696
|
-
|
|
3697
|
-
|
|
3991
|
+
const runtimeHostIpv4 = args.runtime.hostIpv4;
|
|
3992
|
+
if (!runtimeHostIpv4) {
|
|
3993
|
+
throw new Error(
|
|
3994
|
+
`${deploymentProfile === "ucan-store" ? "Service" : "Relay"} runtime did not expose a host IPv4 address.`
|
|
3995
|
+
);
|
|
3698
3996
|
}
|
|
3699
3997
|
let runtime = args.runtime;
|
|
3700
3998
|
let mappedPorts2 = runtime.mappedPorts ?? {};
|
|
3701
3999
|
const setupPort = mappedPorts2["80"]?.host ?? null;
|
|
3702
4000
|
if (!setupPort) {
|
|
3703
|
-
throw new Error(
|
|
4001
|
+
throw new Error(
|
|
4002
|
+
`${deploymentProfile === "ucan-store" ? "Service" : "Relay"} runtime did not expose the temporary setup endpoint.`
|
|
4003
|
+
);
|
|
4004
|
+
}
|
|
4005
|
+
if (deploymentProfile === "ucan-store") {
|
|
4006
|
+
const serviceHostIpv4 = runtimeHostIpv4;
|
|
4007
|
+
const serviceProxyUrl = runtime.proxyUrl;
|
|
4008
|
+
if (!serviceProxyUrl) {
|
|
4009
|
+
throw new Error("Service runtime did not expose a proxy URL.");
|
|
4010
|
+
}
|
|
4011
|
+
const walletAddress2 = this.state.wallet.address;
|
|
4012
|
+
if (!walletAddress2) {
|
|
4013
|
+
throw new Error("A connected wallet is required to configure the ucan-store bootstrap package.");
|
|
4014
|
+
}
|
|
4015
|
+
const bootstrapValidation = buildUcanStoreBootstrapPackage({
|
|
4016
|
+
input: this.state.ucanStoreBootstrap,
|
|
4017
|
+
operatorAddress: walletAddress2,
|
|
4018
|
+
serviceOriginFallback: serviceProxyUrl,
|
|
4019
|
+
pwaOriginFallback: currentPageOrigin()
|
|
4020
|
+
});
|
|
4021
|
+
if (!bootstrapValidation.valid || !bootstrapValidation.bootstrapPackage) {
|
|
4022
|
+
throw new Error(
|
|
4023
|
+
bootstrapValidation.errors[0] ?? "The ucan-store bootstrap package is invalid."
|
|
4024
|
+
);
|
|
4025
|
+
}
|
|
4026
|
+
this.emitProgress({
|
|
4027
|
+
stage: "deployment-confirmed",
|
|
4028
|
+
label: "Configuring service",
|
|
4029
|
+
progress: 93,
|
|
4030
|
+
status: "info",
|
|
4031
|
+
itemHash: args.itemHash,
|
|
4032
|
+
detail: "Waiting for the guest setup endpoint before applying the upload service configuration."
|
|
4033
|
+
});
|
|
4034
|
+
const setupHealth = await waitForSetupEndpoint({
|
|
4035
|
+
hostIpv4: serviceHostIpv4,
|
|
4036
|
+
setupPort,
|
|
4037
|
+
fetch: (url, init) => fetch(url, init),
|
|
4038
|
+
attempts: 15,
|
|
4039
|
+
delayMs: 4e3,
|
|
4040
|
+
httpTimeoutMs: 1e4,
|
|
4041
|
+
onAttempt: (result, attempt, attempts) => {
|
|
4042
|
+
this.emitProgress({
|
|
4043
|
+
stage: "deployment-confirmed",
|
|
4044
|
+
label: "Waiting for guest setup",
|
|
4045
|
+
progress: 93,
|
|
4046
|
+
status: result.ok ? "success" : "info",
|
|
4047
|
+
itemHash: args.itemHash,
|
|
4048
|
+
detail: result.ok ? `Setup endpoint ${attempt}/${attempts}: ready at http://${serviceHostIpv4}:${setupPort}/health.` : `Setup endpoint ${attempt}/${attempts}: waiting for http://${serviceHostIpv4}:${setupPort}/health.`
|
|
4049
|
+
});
|
|
4050
|
+
}
|
|
4051
|
+
});
|
|
4052
|
+
if (!setupHealth.ok) {
|
|
4053
|
+
throw new Error(
|
|
4054
|
+
`Service setup endpoint did not become reachable at http://${serviceHostIpv4}:${setupPort}/health.`
|
|
4055
|
+
);
|
|
4056
|
+
}
|
|
4057
|
+
this.emitProgress({
|
|
4058
|
+
stage: "deployment-confirmed",
|
|
4059
|
+
label: "Applying service config",
|
|
4060
|
+
progress: 94,
|
|
4061
|
+
status: "info",
|
|
4062
|
+
itemHash: args.itemHash,
|
|
4063
|
+
detail: "Publishing the public HTTPS origin into the guest upload service configuration."
|
|
4064
|
+
});
|
|
4065
|
+
const configureResult = await configureUcanStore({
|
|
4066
|
+
hostIpv4: serviceHostIpv4,
|
|
4067
|
+
publicIpv6: runtime.ipv6,
|
|
4068
|
+
setupPort,
|
|
4069
|
+
proxyUrl: serviceProxyUrl,
|
|
4070
|
+
webauthnOrigin: serviceProxyUrl,
|
|
4071
|
+
adminDid: bootstrapValidation.bootstrapPackage.adminDid,
|
|
4072
|
+
bootstrapPackage: bootstrapValidation.bootstrapPackage,
|
|
4073
|
+
fetch: (url, init) => fetch(url, init),
|
|
4074
|
+
timeoutMs: 18e4
|
|
4075
|
+
});
|
|
4076
|
+
if (!isConfirmedGuestSetupResult(configureResult)) {
|
|
4077
|
+
throw new Error(
|
|
4078
|
+
`Service guest configuration could not be confirmed at http://${serviceHostIpv4}:${setupPort}/configure.`
|
|
4079
|
+
);
|
|
4080
|
+
}
|
|
4081
|
+
this.emitProgress({
|
|
4082
|
+
stage: "deployment-confirmed",
|
|
4083
|
+
label: "Waiting for service metadata",
|
|
4084
|
+
progress: 95,
|
|
4085
|
+
status: "info",
|
|
4086
|
+
itemHash: args.itemHash,
|
|
4087
|
+
detail: "Waiting for the upload service metadata endpoint to report the public service DID and PWA environment."
|
|
4088
|
+
});
|
|
4089
|
+
const serviceMetadata = await fetchUcGoPeerMetadata({
|
|
4090
|
+
hostIpv4: serviceHostIpv4,
|
|
4091
|
+
setupPort,
|
|
4092
|
+
fetch: (url, init) => fetch(url, init),
|
|
4093
|
+
attempts: 80,
|
|
4094
|
+
delayMs: 3e3,
|
|
4095
|
+
timeoutMs: 24e4,
|
|
4096
|
+
isReady: ({ payload, ok }) => {
|
|
4097
|
+
if (!ok || !payload || typeof payload !== "object") return false;
|
|
4098
|
+
const metadata2 = payload.metadata && typeof payload.metadata === "object" ? payload.metadata : null;
|
|
4099
|
+
const pwaEnv = metadata2?.pwa_env && typeof metadata2.pwa_env === "object" ? metadata2.pwa_env : null;
|
|
4100
|
+
return Boolean(
|
|
4101
|
+
typeof metadata2?.upload_service_did === "string" && metadata2.upload_service_did.length > 0 && typeof pwaEnv?.VITE_UPLOAD_SERVICE_URL === "string" && pwaEnv.VITE_UPLOAD_SERVICE_URL.length > 0
|
|
4102
|
+
);
|
|
4103
|
+
},
|
|
4104
|
+
onAttempt: ({ ready, attempt, attempts, requestUrl }) => {
|
|
4105
|
+
this.emitProgress({
|
|
4106
|
+
stage: "deployment-confirmed",
|
|
4107
|
+
label: ready ? "Service metadata ready" : "Waiting for service metadata",
|
|
4108
|
+
progress: 95,
|
|
4109
|
+
status: ready ? "success" : "info",
|
|
4110
|
+
itemHash: args.itemHash,
|
|
4111
|
+
detail: ready ? `Service metadata ${attempt}/${attempts}: public upload service wiring is ready.` : `Service metadata ${attempt}/${attempts}: waiting for ${requestUrl}.`
|
|
4112
|
+
});
|
|
4113
|
+
}
|
|
4114
|
+
});
|
|
4115
|
+
const metadata = serviceMetadata && typeof serviceMetadata === "object" ? serviceMetadata.metadata ?? null : null;
|
|
4116
|
+
if (!metadata || typeof metadata !== "object" || typeof metadata.upload_service_did !== "string") {
|
|
4117
|
+
throw new Error(
|
|
4118
|
+
"Service metadata did not include the public upload service DID."
|
|
4119
|
+
);
|
|
4120
|
+
}
|
|
4121
|
+
return;
|
|
4122
|
+
}
|
|
4123
|
+
if (!profile) return;
|
|
4124
|
+
const walletAddress = this.state.wallet.address;
|
|
4125
|
+
if (!walletAddress) {
|
|
4126
|
+
throw new Error("A connected wallet is required to register relay bootstrap addresses.");
|
|
3704
4127
|
}
|
|
3705
4128
|
let bootstrapSignalRelayMetadata = null;
|
|
3706
4129
|
if (profile === "orbitdb-relay") {
|
|
@@ -3713,7 +4136,7 @@ var SponsorRelayController = class {
|
|
|
3713
4136
|
detail: "Waiting for the guest setup endpoint before collecting relay metadata."
|
|
3714
4137
|
});
|
|
3715
4138
|
const setupHealth = await waitForSetupEndpoint({
|
|
3716
|
-
hostIpv4:
|
|
4139
|
+
hostIpv4: runtimeHostIpv4,
|
|
3717
4140
|
setupPort,
|
|
3718
4141
|
fetch: (url, init) => fetch(url, init),
|
|
3719
4142
|
attempts: 15,
|
|
@@ -3726,13 +4149,13 @@ var SponsorRelayController = class {
|
|
|
3726
4149
|
progress: 93,
|
|
3727
4150
|
status: result.ok ? "success" : "info",
|
|
3728
4151
|
itemHash: args.itemHash,
|
|
3729
|
-
detail: result.ok ? `Setup endpoint ${attempt}/${attempts}: ready at http://${
|
|
4152
|
+
detail: result.ok ? `Setup endpoint ${attempt}/${attempts}: ready at http://${runtimeHostIpv4}:${setupPort}/health.` : `Setup endpoint ${attempt}/${attempts}: waiting for http://${runtimeHostIpv4}:${setupPort}/health.`
|
|
3730
4153
|
});
|
|
3731
4154
|
}
|
|
3732
4155
|
});
|
|
3733
4156
|
if (!setupHealth.ok) {
|
|
3734
4157
|
throw new Error(
|
|
3735
|
-
`Relay setup endpoint did not become reachable at http://${
|
|
4158
|
+
`Relay setup endpoint did not become reachable at http://${runtimeHostIpv4}:${setupPort}/health.`
|
|
3736
4159
|
);
|
|
3737
4160
|
}
|
|
3738
4161
|
this.emitProgress({
|
|
@@ -3749,7 +4172,7 @@ var SponsorRelayController = class {
|
|
|
3749
4172
|
throw new Error("OrbitDB relay runtime is missing required mapped TCP/WS ports.");
|
|
3750
4173
|
}
|
|
3751
4174
|
const configureResult = await configureOrbitdbRelaySetup2({
|
|
3752
|
-
hostIpv4:
|
|
4175
|
+
hostIpv4: runtimeHostIpv4,
|
|
3753
4176
|
publicIpv6: args.runtime.ipv6,
|
|
3754
4177
|
setupPort,
|
|
3755
4178
|
tcpPort,
|
|
@@ -3762,7 +4185,7 @@ var SponsorRelayController = class {
|
|
|
3762
4185
|
fetch: (url, init) => fetch(url, init),
|
|
3763
4186
|
timeoutMs: 18e4
|
|
3764
4187
|
});
|
|
3765
|
-
if (!
|
|
4188
|
+
if (!isConfirmedGuestSetupResult(configureResult)) {
|
|
3766
4189
|
throw new Error(
|
|
3767
4190
|
`Relay guest configuration could not be confirmed at http://${args.runtime.hostIpv4}:${setupPort}/configure.`
|
|
3768
4191
|
);
|
|
@@ -3820,7 +4243,7 @@ var SponsorRelayController = class {
|
|
|
3820
4243
|
"Relay runtime lost its host IPv4 address while waiting for HTTPS activation."
|
|
3821
4244
|
);
|
|
3822
4245
|
}
|
|
3823
|
-
const
|
|
4246
|
+
const runtimeHostIpv42 = runtime.hostIpv4;
|
|
3824
4247
|
const activeProxyUrl = runtime.webAccess?.active === true ? runtime.proxyUrl ?? null : null;
|
|
3825
4248
|
this.emitProgress({
|
|
3826
4249
|
stage: "deployment-confirmed",
|
|
@@ -3833,13 +4256,13 @@ var SponsorRelayController = class {
|
|
|
3833
4256
|
const record = {
|
|
3834
4257
|
deploymentToken: args.deploymentToken,
|
|
3835
4258
|
profile,
|
|
3836
|
-
ownerAddress:
|
|
4259
|
+
ownerAddress: walletAddress,
|
|
3837
4260
|
instanceItemHash: args.itemHash,
|
|
3838
4261
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3839
4262
|
expiresAt: new Date(Date.now() + 30 * 6e4).toISOString(),
|
|
3840
4263
|
status: "pending",
|
|
3841
4264
|
runtime: {
|
|
3842
|
-
publicIpv4:
|
|
4265
|
+
publicIpv4: runtimeHostIpv42,
|
|
3843
4266
|
publicIpv6: runtime.ipv6 ?? null,
|
|
3844
4267
|
proxyUrl: activeProxyUrl,
|
|
3845
4268
|
mappedPorts: mappedPorts2
|
|
@@ -3853,7 +4276,7 @@ var SponsorRelayController = class {
|
|
|
3853
4276
|
}
|
|
3854
4277
|
};
|
|
3855
4278
|
const bootstrapConfigPublication = await publishVmBootstrapConfig({
|
|
3856
|
-
sender:
|
|
4279
|
+
sender: walletAddress,
|
|
3857
4280
|
record,
|
|
3858
4281
|
signer: personalSign,
|
|
3859
4282
|
hasher: sha256Hex,
|
|
@@ -3880,7 +4303,7 @@ var SponsorRelayController = class {
|
|
|
3880
4303
|
});
|
|
3881
4304
|
const bootstrapConfigSignal = await waitForVmBootstrapConfigSignal({
|
|
3882
4305
|
deploymentToken: args.deploymentToken,
|
|
3883
|
-
ownerAddress:
|
|
4306
|
+
ownerAddress: walletAddress,
|
|
3884
4307
|
instanceItemHash: args.itemHash,
|
|
3885
4308
|
fetch: asJsonFetch,
|
|
3886
4309
|
apiHost: this.client.apiHost,
|
|
@@ -4052,7 +4475,7 @@ var SponsorRelayController = class {
|
|
|
4052
4475
|
detail: "Guest bootstrap registration was delayed. Publishing the relay bootstrap record from the browser."
|
|
4053
4476
|
});
|
|
4054
4477
|
const fallbackPublication = await publishRelayBootstrapRegistration({
|
|
4055
|
-
sender:
|
|
4478
|
+
sender: walletAddress,
|
|
4056
4479
|
signer: personalSign,
|
|
4057
4480
|
hasher: sha256Hex,
|
|
4058
4481
|
fetch: asJsonFetch,
|
|
@@ -4072,7 +4495,7 @@ var SponsorRelayController = class {
|
|
|
4072
4495
|
fallbackPublication
|
|
4073
4496
|
});
|
|
4074
4497
|
const fallbackVisibleRegistration = await waitForRelayBootstrapRegistration({
|
|
4075
|
-
sender:
|
|
4498
|
+
sender: walletAddress,
|
|
4076
4499
|
registrationId,
|
|
4077
4500
|
peerId,
|
|
4078
4501
|
fetch: asJsonFetch,
|
|
@@ -4105,7 +4528,7 @@ var SponsorRelayController = class {
|
|
|
4105
4528
|
if (profile === "uc-go-peer" && args.deploymentToken) {
|
|
4106
4529
|
let cleanupAggregateItemHash = null;
|
|
4107
4530
|
await deleteVmBootstrapConfig({
|
|
4108
|
-
sender:
|
|
4531
|
+
sender: walletAddress,
|
|
4109
4532
|
deploymentToken: args.deploymentToken,
|
|
4110
4533
|
signer: personalSign,
|
|
4111
4534
|
hasher: sha256Hex,
|
|
@@ -4271,17 +4694,35 @@ var SponsorRelayController = class {
|
|
|
4271
4694
|
});
|
|
4272
4695
|
return;
|
|
4273
4696
|
}
|
|
4697
|
+
const currentProfile = deploymentProfileForManifest(this.state.manifest);
|
|
4274
4698
|
const hasConfirmedBootstrapRegistration = this.state.bootstrapRegistrations.some(
|
|
4275
4699
|
(entry) => entry.instanceItemHash === itemHash && entry.confirmed
|
|
4276
4700
|
);
|
|
4701
|
+
if (currentProfile === "ucan-store") {
|
|
4702
|
+
this.emitProgress({
|
|
4703
|
+
stage: "completed",
|
|
4704
|
+
label: deploymentReadyLabel(currentProfile),
|
|
4705
|
+
progress: 100,
|
|
4706
|
+
status: "success",
|
|
4707
|
+
itemHash,
|
|
4708
|
+
detail: deploymentReadyDetail(
|
|
4709
|
+
currentProfile,
|
|
4710
|
+
"Runtime networking is available and the deployment finished successfully."
|
|
4711
|
+
)
|
|
4712
|
+
});
|
|
4713
|
+
return;
|
|
4714
|
+
}
|
|
4277
4715
|
if (hasConfirmedBootstrapRegistration) {
|
|
4278
4716
|
this.emitProgress({
|
|
4279
4717
|
stage: "completed",
|
|
4280
|
-
label:
|
|
4718
|
+
label: deploymentReadyLabel(currentProfile),
|
|
4281
4719
|
progress: 100,
|
|
4282
4720
|
status: "success",
|
|
4283
4721
|
itemHash,
|
|
4284
|
-
detail:
|
|
4722
|
+
detail: deploymentReadyDetail(
|
|
4723
|
+
currentProfile,
|
|
4724
|
+
"Runtime networking is available and the relay bootstrap registration is confirmed on Aleph."
|
|
4725
|
+
)
|
|
4285
4726
|
});
|
|
4286
4727
|
return;
|
|
4287
4728
|
}
|
|
@@ -4291,7 +4732,7 @@ var SponsorRelayController = class {
|
|
|
4291
4732
|
progress: 92,
|
|
4292
4733
|
status: "info",
|
|
4293
4734
|
itemHash,
|
|
4294
|
-
detail:
|
|
4735
|
+
detail: `Deployment processed and runtime networking is available. Finishing ${deploymentNoun(currentProfile)} setup and verification.`
|
|
4295
4736
|
});
|
|
4296
4737
|
}
|
|
4297
4738
|
canSkipRuntimeRefresh(instance) {
|
|
@@ -4404,6 +4845,15 @@ var SponsorRelayController = class {
|
|
|
4404
4845
|
setInstanceName(instanceName) {
|
|
4405
4846
|
this.patch({ instanceName });
|
|
4406
4847
|
}
|
|
4848
|
+
setUcanStoreBootstrapField(field, value) {
|
|
4849
|
+
this.patch({
|
|
4850
|
+
ucanStoreBootstrap: {
|
|
4851
|
+
...this.state.ucanStoreBootstrap,
|
|
4852
|
+
[field]: value
|
|
4853
|
+
},
|
|
4854
|
+
showAdvanced: this.state.showAdvanced || Boolean(value.trim())
|
|
4855
|
+
});
|
|
4856
|
+
}
|
|
4407
4857
|
setTierId(tierId) {
|
|
4408
4858
|
this.patch({ tierId });
|
|
4409
4859
|
this.recomputePricingSummary();
|
|
@@ -4489,6 +4939,7 @@ var SponsorRelayController = class {
|
|
|
4489
4939
|
}
|
|
4490
4940
|
}
|
|
4491
4941
|
async refresh() {
|
|
4942
|
+
const currentProfile = deploymentProfileForManifest(this.state.manifest);
|
|
4492
4943
|
this.trace("refresh:start", {
|
|
4493
4944
|
wallet: this.state.wallet.address,
|
|
4494
4945
|
manifestUrl: this.state.manifestUrl,
|
|
@@ -4497,7 +4948,7 @@ var SponsorRelayController = class {
|
|
|
4497
4948
|
this.patch({
|
|
4498
4949
|
busy: { refreshing: true },
|
|
4499
4950
|
errorText: null,
|
|
4500
|
-
statusText: "Refreshing relay
|
|
4951
|
+
statusText: currentProfile === "ucan-store" ? "Refreshing service deployment data" : "Refreshing relay deployment data"
|
|
4501
4952
|
});
|
|
4502
4953
|
try {
|
|
4503
4954
|
const [pricingSummary, crns] = await Promise.all([
|
|
@@ -4509,6 +4960,8 @@ var SponsorRelayController = class {
|
|
|
4509
4960
|
manifestJson: this.state.manifestJson
|
|
4510
4961
|
}).catch((error) => manifestLoadErrorState(error));
|
|
4511
4962
|
const manifest = manifestState.manifest;
|
|
4963
|
+
const resolvedProfile = deploymentProfileForManifest(manifest);
|
|
4964
|
+
const bootstrapEnabled = supportsBootstrapRegistrationsForManifest(manifest);
|
|
4512
4965
|
let balance = this.state.balance;
|
|
4513
4966
|
let instances = [];
|
|
4514
4967
|
let bootstrapRegistrations = [];
|
|
@@ -4517,10 +4970,10 @@ var SponsorRelayController = class {
|
|
|
4517
4970
|
const [nextBalance, rawInstances, rawBootstrapPosts] = await Promise.all([
|
|
4518
4971
|
this.client.fetchBalance(this.state.wallet.address),
|
|
4519
4972
|
this.state.showInstances ? this.client.fetchInstances(this.state.wallet.address) : Promise.resolve([]),
|
|
4520
|
-
fetchAlephBootstrapPosts({
|
|
4973
|
+
bootstrapEnabled ? fetchAlephBootstrapPosts({
|
|
4521
4974
|
apiHost: this.client.apiHost,
|
|
4522
4975
|
fetch
|
|
4523
|
-
}).catch(() => [])
|
|
4976
|
+
}).catch(() => []) : Promise.resolve([])
|
|
4524
4977
|
]);
|
|
4525
4978
|
balance = nextBalance;
|
|
4526
4979
|
instances = await Promise.all(
|
|
@@ -4650,7 +5103,7 @@ var SponsorRelayController = class {
|
|
|
4650
5103
|
bootstrapRegistrations,
|
|
4651
5104
|
orphanBootstrapRegistrations,
|
|
4652
5105
|
busy: { refreshing: false },
|
|
4653
|
-
statusText: "Relay
|
|
5106
|
+
statusText: resolvedProfile === "ucan-store" ? "Service deployment data ready" : "Relay deployment data ready"
|
|
4654
5107
|
});
|
|
4655
5108
|
this.trace("refresh:success", {
|
|
4656
5109
|
manifestValid: manifestState.valid,
|
|
@@ -4687,6 +5140,16 @@ var SponsorRelayController = class {
|
|
|
4687
5140
|
});
|
|
4688
5141
|
return;
|
|
4689
5142
|
}
|
|
5143
|
+
if (deploymentProfileForManifest(this.state.manifest) === "ucan-store") {
|
|
5144
|
+
const draftErrors = draftUcanStoreBootstrapErrors({
|
|
5145
|
+
input: this.state.ucanStoreBootstrap,
|
|
5146
|
+
operatorAddress: this.state.wallet.address
|
|
5147
|
+
});
|
|
5148
|
+
if (draftErrors.length > 0) {
|
|
5149
|
+
this.patch({ errorText: draftErrors[0] });
|
|
5150
|
+
return;
|
|
5151
|
+
}
|
|
5152
|
+
}
|
|
4690
5153
|
this.patch({
|
|
4691
5154
|
busy: { deploying: true },
|
|
4692
5155
|
errorText: null,
|
|
@@ -4736,7 +5199,7 @@ var SponsorRelayController = class {
|
|
|
4736
5199
|
detail: `Trying ${crnDisplayName}`
|
|
4737
5200
|
});
|
|
4738
5201
|
try {
|
|
4739
|
-
const profile =
|
|
5202
|
+
const profile = deploymentProfileForManifest(this.state.manifest);
|
|
4740
5203
|
attemptProfile = profile;
|
|
4741
5204
|
const sshPublicKey = profile === "uc-go-peer" ? appendDeploymentTokenToSshPublicKey(
|
|
4742
5205
|
this.state.sshPublicKey.trim(),
|
|
@@ -4955,11 +5418,14 @@ var SponsorRelayController = class {
|
|
|
4955
5418
|
this.lastCompletedDeploymentHash = result.itemHash;
|
|
4956
5419
|
this.emitProgress({
|
|
4957
5420
|
stage: "completed",
|
|
4958
|
-
label:
|
|
5421
|
+
label: deploymentReadyLabel(attemptProfile),
|
|
4959
5422
|
progress: 100,
|
|
4960
5423
|
status: "success",
|
|
4961
5424
|
itemHash: result.itemHash,
|
|
4962
|
-
detail:
|
|
5425
|
+
detail: deploymentReadyDetail(
|
|
5426
|
+
attemptProfile,
|
|
5427
|
+
"Relay runtime, setup, metadata, and bootstrap registration are confirmed."
|
|
5428
|
+
)
|
|
4963
5429
|
});
|
|
4964
5430
|
return;
|
|
4965
5431
|
} catch (error) {
|
|
@@ -5033,11 +5499,14 @@ var SponsorRelayController = class {
|
|
|
5033
5499
|
this.lastCompletedDeploymentHash = attemptItemHash;
|
|
5034
5500
|
this.emitProgress({
|
|
5035
5501
|
stage: "completed",
|
|
5036
|
-
label:
|
|
5502
|
+
label: deploymentReadyLabel(attemptProfile),
|
|
5037
5503
|
progress: 100,
|
|
5038
5504
|
status: "success",
|
|
5039
5505
|
itemHash: attemptItemHash,
|
|
5040
|
-
detail:
|
|
5506
|
+
detail: deploymentReadyDetail(
|
|
5507
|
+
attemptProfile,
|
|
5508
|
+
"The relay completed startup after a transient UI polling error. Runtime and bootstrap registration are confirmed."
|
|
5509
|
+
)
|
|
5041
5510
|
});
|
|
5042
5511
|
return;
|
|
5043
5512
|
}
|
|
@@ -5064,11 +5533,14 @@ var SponsorRelayController = class {
|
|
|
5064
5533
|
this.lastCompletedDeploymentHash = attemptItemHash;
|
|
5065
5534
|
this.emitProgress({
|
|
5066
5535
|
stage: "completed",
|
|
5067
|
-
label:
|
|
5536
|
+
label: deploymentReadyLabel(attemptProfile),
|
|
5068
5537
|
progress: 100,
|
|
5069
5538
|
status: "success",
|
|
5070
5539
|
itemHash: attemptItemHash,
|
|
5071
|
-
detail:
|
|
5540
|
+
detail: deploymentReadyDetail(
|
|
5541
|
+
attemptProfile,
|
|
5542
|
+
"The relay completed startup after a transient browser-side polling error. Runtime and bootstrap registration are confirmed."
|
|
5543
|
+
)
|
|
5072
5544
|
});
|
|
5073
5545
|
return;
|
|
5074
5546
|
}
|