sideload wip, websockets, styling, multiple todos (#2865)

* sideload wip, websockets, styling, multiple todos

* sideload

* misc backend updates

* chore: comments

* prep for license and instructions display

* comment for Matt

* s9pk updates and 040 sdk

* fix dependency error for actions

* 0.4.0-beta.1

* beta.2

---------

Co-authored-by: Aiden McClelland <me@drbonez.dev>
Co-authored-by: waterplea <alexander@inkin.ru>
Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
This commit is contained in:
Matt Hill
2025-04-10 13:51:05 -06:00
committed by GitHub
parent ab4336cfd7
commit fc2be42418
88 changed files with 773 additions and 965 deletions

View File

@@ -66,7 +66,9 @@ export async function checkDependencies<
return dep.requirement.kind !== "running" || dep.result.isRunning
}
const actionsSatisfied = (packageId: DependencyId) =>
Object.keys(find(packageId).result.requestedActions).length === 0
Object.entries(find(packageId).result.requestedActions).filter(
([_, req]) => req.active && req.request.severity === "critical",
).length === 0
const healthCheckSatisfied = (
packageId: DependencyId,
healthCheckId?: HealthCheckId,
@@ -129,7 +131,9 @@ export async function checkDependencies<
}
const throwIfActionsNotSatisfied = (packageId: DependencyId) => {
const dep = find(packageId)
const reqs = Object.keys(dep.result.requestedActions)
const reqs = Object.entries(dep.result.requestedActions)
.filter(([_, req]) => req.active && req.request.severity === "critical")
.map(([id, _]) => id)
if (reqs.length) {
throw new Error(
`The following action requests have not been fulfilled: ${reqs.join(", ")}`,

View File

@@ -1,8 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { PasswordType } from "./PasswordType"
export type LoginParams = {
password: PasswordType | null
ephemeral: boolean
metadata: any
}
export type LoginParams = { password: PasswordType | null; ephemeral: boolean }

View File

@@ -14,7 +14,7 @@ export type PackageVersionInfo = {
icon: DataUrl
description: Description
releaseNotes: string
gitHash: GitHash
gitHash: GitHash | null
license: string
wrapperRepo: string
upstreamRepo: string

View File

@@ -1,3 +1,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type Session = { loggedIn: string; lastActive: string; metadata: any }
export type Session = {
loggedIn: string
lastActive: string
userAgent: string | null
}

View File

@@ -1,5 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type Sessions = {
[key: string]: { loggedIn: string; lastActive: string; metadata: any }
[key: string]: {
loggedIn: string
lastActive: string
userAgent: string | null
}
}

View File

@@ -1,6 +1,14 @@
import { DataUrl, Manifest, MerkleArchiveCommitment } from "../osBindings"
import {
DataUrl,
DependencyMetadata,
Manifest,
MerkleArchiveCommitment,
PackageId,
} from "../osBindings"
import { ArrayBufferReader, MerkleArchive } from "./merkleArchive"
import mime from "mime-types"
import { DirectoryContents } from "./merkleArchive/directoryContents"
import { FileContents } from "./merkleArchive/fileContents"
const magicAndVersion = new Uint8Array([59, 59, 2])
@@ -65,4 +73,63 @@ export class S9pk {
).toString("base64")
)
}
async dependencyMetadataFor(id: PackageId) {
const entry = this.archive.contents.getPath([
"dependencies",
id,
"metadata.json",
])
if (!entry) return null
return JSON.parse(
new TextDecoder().decode(await entry.verifiedFileContents()),
) as { title: string }
}
async dependencyIconFor(id: PackageId) {
const dir = this.archive.contents.getPath(["dependencies", id])
if (!dir || !(dir.contents instanceof DirectoryContents)) return null
const iconName = Object.keys(dir.contents.contents).find(
(name) =>
name.startsWith("icon.") &&
(mime.contentType(name) || null)?.startsWith("image/"),
)
if (!iconName) return null
return (
`data:${mime.contentType(iconName)};base64,` +
Buffer.from(
await dir.contents.getPath([iconName])!.verifiedFileContents(),
).toString("base64")
)
}
async dependencyMetadata(): Promise<Record<PackageId, DependencyMetadata>> {
return Object.fromEntries(
await Promise.all(
Object.entries(this.manifest.dependencies).map(async ([id, info]) => [
id,
{
...(await this.dependencyMetadataFor(id)),
icon: await this.dependencyIconFor(id),
description: info.description,
optional: info.optional,
},
]),
),
)
}
async instructions(): Promise<string> {
const file = this.archive.contents.getPath(["instructions.md"])
if (!file || !(file.contents instanceof FileContents))
throw new Error("instructions.md not found in archive")
return new TextDecoder().decode(await file.verifiedFileContents())
}
async license(): Promise<string> {
const file = this.archive.contents.getPath(["LICENSE.md"])
if (!file || !(file.contents instanceof FileContents))
throw new Error("instructions.md not found in archive")
return new TextDecoder().decode(await file.verifiedFileContents())
}
}