boo-flash 0.1.3 → 0.1.4
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/app.js +54 -10
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -3434,6 +3434,34 @@ var moduleDirectory = dirname3(fileURLToPath2(import.meta.url));
|
|
|
3434
3434
|
function bytes(n) {
|
|
3435
3435
|
return n >= 1024 ** 3 ? `${(n / 1024 ** 3).toFixed(1)} GiB` : `${(n / 1024 ** 2).toFixed(1)} MiB`;
|
|
3436
3436
|
}
|
|
3437
|
+
function localTimestamp(value) {
|
|
3438
|
+
const date = new Date(value);
|
|
3439
|
+
if (!Number.isFinite(date.getTime())) throw new Error("Invalid image timestamp.");
|
|
3440
|
+
const part = (number) => String(number).padStart(2, "0");
|
|
3441
|
+
const minutes = -date.getTimezoneOffset();
|
|
3442
|
+
const offset = `${minutes < 0 ? "-" : "+"}${part(Math.floor(Math.abs(minutes) / 60))}:${part(Math.abs(minutes) % 60)}`;
|
|
3443
|
+
return `${date.getFullYear()}-${part(date.getMonth() + 1)}-${part(date.getDate())} ${part(date.getHours())}:${part(date.getMinutes())}:${part(date.getSeconds())} ${offset}`;
|
|
3444
|
+
}
|
|
3445
|
+
function releaseTimestamp(headers) {
|
|
3446
|
+
const values = headers.split(/\r?\n/).flatMap((line) => {
|
|
3447
|
+
const match = /^last-modified:\s*(.*?)\s*$/i.exec(line);
|
|
3448
|
+
return match ? [match[1]] : [];
|
|
3449
|
+
});
|
|
3450
|
+
if (values.length !== 1 || !Number.isFinite(Date.parse(values[0]))) {
|
|
3451
|
+
throw new Error("The Boo release publication time is invalid.");
|
|
3452
|
+
}
|
|
3453
|
+
return new Date(values[0]).toISOString();
|
|
3454
|
+
}
|
|
3455
|
+
function releaseChannel(response) {
|
|
3456
|
+
let separator = response.indexOf("\r\n\r\n");
|
|
3457
|
+
let length = 4;
|
|
3458
|
+
if (separator < 0) {
|
|
3459
|
+
separator = response.indexOf("\n\n");
|
|
3460
|
+
length = 2;
|
|
3461
|
+
}
|
|
3462
|
+
if (separator < 0) throw new Error("The Boo release channel response is invalid.");
|
|
3463
|
+
return { channel: JSON.parse(response.slice(separator + length)), timestamp: releaseTimestamp(response.slice(0, separator)) };
|
|
3464
|
+
}
|
|
3437
3465
|
async function prepareSafeRemoval(platform3, disk, signal, authorize2, revalidate, update) {
|
|
3438
3466
|
if (platform3.finalAuthorization) {
|
|
3439
3467
|
update({ stage: "Authorizing", detail: "Refreshing Linux authorization before safe power-off." });
|
|
@@ -3456,7 +3484,21 @@ async function discoverImages(signal) {
|
|
|
3456
3484
|
...fresh ? ["--header", "Cache-Control: no-cache"] : [],
|
|
3457
3485
|
url
|
|
3458
3486
|
], signal, { limit: 1024 ** 2 }));
|
|
3459
|
-
const
|
|
3487
|
+
const channelUrl = `${releaseOrigin}/channels/main.json`;
|
|
3488
|
+
const { channel, timestamp } = releaseChannel(await command([
|
|
3489
|
+
"curl",
|
|
3490
|
+
"--fail",
|
|
3491
|
+
"--silent",
|
|
3492
|
+
"--show-error",
|
|
3493
|
+
"--proto",
|
|
3494
|
+
"=https",
|
|
3495
|
+
"--header",
|
|
3496
|
+
"Cache-Control: no-cache",
|
|
3497
|
+
"--suppress-connect-headers",
|
|
3498
|
+
"--dump-header",
|
|
3499
|
+
"-",
|
|
3500
|
+
channelUrl
|
|
3501
|
+
], signal, { limit: 1024 ** 2 }));
|
|
3460
3502
|
if (channel?.schema !== 1 || !releaseVersion.test(channel.version) || !/^[a-f0-9]{40}$/.test(channel.revision) || channel.prefix !== `releases/${channel.version}`) {
|
|
3461
3503
|
throw new Error("The Boo main release channel is invalid.");
|
|
3462
3504
|
}
|
|
@@ -3483,7 +3525,7 @@ async function discoverImages(signal) {
|
|
|
3483
3525
|
rawDigest: artifact.raw_sha256
|
|
3484
3526
|
};
|
|
3485
3527
|
});
|
|
3486
|
-
return { run: build, version: channel.version, revision: channel.revision, images };
|
|
3528
|
+
return { run: build, version: channel.version, revision: channel.revision, timestamp, images };
|
|
3487
3529
|
}
|
|
3488
3530
|
async function discoverCandidates(signal) {
|
|
3489
3531
|
const api = async (path) => JSON.parse(await command(["gh", "api", "--hostname", "github.com", `repos/${repository}/${path}`], signal));
|
|
@@ -3500,6 +3542,7 @@ async function discoverCandidates(signal) {
|
|
|
3500
3542
|
candidates.push({
|
|
3501
3543
|
run: run.id,
|
|
3502
3544
|
revision: match[2],
|
|
3545
|
+
timestamp: new Date(run.created_at).toISOString(),
|
|
3503
3546
|
images: [{
|
|
3504
3547
|
profile: match[1],
|
|
3505
3548
|
id: a.id,
|
|
@@ -3507,7 +3550,7 @@ async function discoverCandidates(signal) {
|
|
|
3507
3550
|
bytes: a.size_in_bytes,
|
|
3508
3551
|
digest: a.digest.slice(7)
|
|
3509
3552
|
}],
|
|
3510
|
-
candidate: { number: run.run_number,
|
|
3553
|
+
candidate: { number: run.run_number, title: cleanText(run.display_title ?? "") }
|
|
3511
3554
|
});
|
|
3512
3555
|
if (candidates.length === 10) return candidates;
|
|
3513
3556
|
}
|
|
@@ -3565,7 +3608,7 @@ var FlashBackend = class {
|
|
|
3565
3608
|
async catalog(signal) {
|
|
3566
3609
|
if (!this.demo) return discoverImages(signal);
|
|
3567
3610
|
await delay(350, void 0, { signal });
|
|
3568
|
-
return { run: 149, version: "0.1.0+149", revision: "9b7574859120add5a1a478bc7923aeb1629be4ba", images: profiles.map((profile, index) => ({
|
|
3611
|
+
return { run: 149, version: "0.1.0+149", revision: "9b7574859120add5a1a478bc7923aeb1629be4ba", timestamp: "2026-08-28T14:23:45Z", images: profiles.map((profile, index) => ({
|
|
3569
3612
|
profile,
|
|
3570
3613
|
id: index,
|
|
3571
3614
|
name: `demo-${profile}`,
|
|
@@ -3578,8 +3621,9 @@ var FlashBackend = class {
|
|
|
3578
3621
|
const catalog = await this.catalog(signal);
|
|
3579
3622
|
return this.demo === "empty" ? [] : [{
|
|
3580
3623
|
...catalog,
|
|
3624
|
+
timestamp: "2026-08-29T01:02:03Z",
|
|
3581
3625
|
images: [catalog.images[0]],
|
|
3582
|
-
candidate: { number: 1,
|
|
3626
|
+
candidate: { number: 1, title: "Simulated candidate" }
|
|
3583
3627
|
}];
|
|
3584
3628
|
}
|
|
3585
3629
|
async disks(signal, staging = tmpdir4(), unmounted) {
|
|
@@ -4047,7 +4091,7 @@ function App(props) {
|
|
|
4047
4091
|
if (["up", "left"].includes(key.name)) setCursor((n) => Math.max(0, n - 1));
|
|
4048
4092
|
if (key.name === "return" && !key.repeated) activate();
|
|
4049
4093
|
});
|
|
4050
|
-
const row = (label, detail, index, danger = false) => (() => {
|
|
4094
|
+
const row = (label, detail, index, danger = false, detailWhenTight = false) => (() => {
|
|
4051
4095
|
var _el$ = createElement("box"), _el$2 = createElement("text");
|
|
4052
4096
|
insertNode(_el$, _el$2);
|
|
4053
4097
|
setProp(_el$, "paddingX", 1);
|
|
@@ -4057,7 +4101,7 @@ function App(props) {
|
|
|
4057
4101
|
insert(_el$2, label, null);
|
|
4058
4102
|
insert(_el$, createComponent2(Show, {
|
|
4059
4103
|
get when() {
|
|
4060
|
-
return detail && !tight();
|
|
4104
|
+
return detail && (!tight() || detailWhenTight);
|
|
4061
4105
|
},
|
|
4062
4106
|
get children() {
|
|
4063
4107
|
var _el$3 = createElement("text"), _el$4 = createTextNode(` `);
|
|
@@ -4069,7 +4113,7 @@ function App(props) {
|
|
|
4069
4113
|
}
|
|
4070
4114
|
}), null);
|
|
4071
4115
|
effect((_p$) => {
|
|
4072
|
-
var _v$ = detail && !tight() ? compact() ? 2 : 3 : 1, _v$2 = cursor() === index ? palette.selected : palette.panel, _v$3 = danger ? palette.warning : cursor() === index ? palette.accent : palette.foreground, _v$4 = TextAttributes2.BOLD;
|
|
4116
|
+
var _v$ = detail && (!tight() || detailWhenTight) ? compact() ? 2 : 3 : 1, _v$2 = cursor() === index ? palette.selected : palette.panel, _v$3 = danger ? palette.warning : cursor() === index ? palette.accent : palette.foreground, _v$4 = TextAttributes2.BOLD;
|
|
4073
4117
|
_v$ !== _p$.e && (_p$.e = setProp(_el$, "height", _v$, _p$.e));
|
|
4074
4118
|
_v$2 !== _p$.t && (_p$.t = setProp(_el$, "backgroundColor", _v$2, _p$.t));
|
|
4075
4119
|
_v$3 !== _p$.a && (_p$.a = setProp(_el$2, "fg", _v$3, _p$.a));
|
|
@@ -4146,7 +4190,7 @@ function App(props) {
|
|
|
4146
4190
|
var _el$13 = createElement("text");
|
|
4147
4191
|
insert(_el$13, (() => {
|
|
4148
4192
|
var _c$ = memo2(() => !!loading());
|
|
4149
|
-
return () => _c$() ? `${spinner()} Finding latest Boo release...` : memo2(() => !!catalog())() ? `Boo ${catalog().version} / ${catalog().revision.slice(0, 7)}` : "Dependencies needed. Enter to set up.";
|
|
4193
|
+
return () => _c$() ? `${spinner()} Finding latest Boo release...` : memo2(() => !!catalog())() ? `Boo ${catalog().version} / ${catalog().revision.slice(0, 7)} / ${localTimestamp(catalog().timestamp)}` : "Dependencies needed. Enter to set up.";
|
|
4150
4194
|
})());
|
|
4151
4195
|
effect((_$p) => setProp(_el$13, "fg", palette.muted, _$p));
|
|
4152
4196
|
return _el$13;
|
|
@@ -4285,7 +4329,7 @@ function App(props) {
|
|
|
4285
4329
|
get each() {
|
|
4286
4330
|
return candidates().slice(Math.max(0, cursor() - 2), Math.max(3, cursor() + 1));
|
|
4287
4331
|
},
|
|
4288
|
-
children: (c, index) => row(`${c.images[0].profile.toUpperCase()} ${c.revision.slice(0, 7)} #${c.candidate.number}
|
|
4332
|
+
children: (c, index) => row(`${c.images[0].profile.toUpperCase()} ${c.revision.slice(0, 7)} #${c.candidate.number}`, `${localTimestamp(c.timestamp)} ${c.candidate.title}`, index() + Math.max(0, cursor() - 2), false, true)
|
|
4289
4333
|
}));
|
|
4290
4334
|
return _el$31;
|
|
4291
4335
|
})(), (() => {
|