update marketplace url to reflect build version (#2914)

* update marketplace url to reflect build version

* adjust marketplace config

* use helper function to compare urls

* rework some registry stuff

* #2900, #2899, and other registry changes

* alpha.1

* trailing /

* add startosRegistry

* fix migration

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>
Co-authored-by: Aiden McClelland <me@drbonez.dev>
Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
This commit is contained in:
Lucy
2025-04-29 16:12:21 -04:00
committed by GitHub
parent 2adf34fbaf
commit 5c473eb9cc
63 changed files with 733 additions and 470 deletions

View File

@@ -30,7 +30,7 @@ export namespace Mock {
shuttingDown: false,
}
export const RegistryOSUpdate: RR.GetRegistryOsUpdateRes = {
export const RegistryOSUpdate: RR.CheckOsUpdateRes = {
'0.3.6-alpha.17': {
headline: 'v0.3.6-alpha.17',
releaseNotes: '',
@@ -101,16 +101,16 @@ export namespace Mock {
},
img: {},
},
'0.4.0-alpha.0': {
headline: 'v0.4.0-alpha.0',
'0.4.0-alpha.1': {
headline: 'v0.4.0-alpha.1',
releaseNotes: '',
sourceVersion: '>=0.3.5:0 <=0.4.0-alpha.0:0',
sourceVersion: '>=0.3.5:0 <=0.4.0-alpha.1:0',
authorized: ['G24CSA5HNYEPIXJNMK7ZM4KD5SX5N6X4'],
iso: {},
squashfs: {
aarch64: {
publishedAt: '2025-04-21T20:58:48.140749883Z',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.0/startos-0.4.0-alpha.0-33ae46f~dev_aarch64.squashfs',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.1/startos-0.4.0-alpha.1-33ae46f~dev_aarch64.squashfs',
commitment: {
hash: '4elBFVkd/r8hNadKmKtLIs42CoPltMvKe2z3LRqkphk=',
size: 1343500288,
@@ -122,7 +122,7 @@ export namespace Mock {
},
'aarch64-nonfree': {
publishedAt: '2025-04-21T21:07:00.249285116Z',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.0/startos-0.4.0-alpha.0-33ae46f~dev_aarch64-nonfree.squashfs',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.1/startos-0.4.0-alpha.1-33ae46f~dev_aarch64-nonfree.squashfs',
commitment: {
hash: 'MrCEi4jxbmPS7zAiGk/JSKlMsiuKqQy6RbYOxlGHOIQ=',
size: 1653075968,
@@ -134,7 +134,7 @@ export namespace Mock {
},
raspberrypi: {
publishedAt: '2025-04-21T21:16:12.933319237Z',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.0/startos-0.4.0-alpha.0-33ae46f~dev_raspberrypi.squashfs',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.1/startos-0.4.0-alpha.1-33ae46f~dev_raspberrypi.squashfs',
commitment: {
hash: '/XTVQRCqY3RK544PgitlKu7UplXjkmzWoXUh2E4HCw0=',
size: 1490731008,
@@ -146,7 +146,7 @@ export namespace Mock {
},
x86_64: {
publishedAt: '2025-04-21T21:14:20.246908903Z',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.0/startos-0.4.0-alpha.0-33ae46f~dev_x86_64.squashfs',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.1/startos-0.4.0-alpha.1-33ae46f~dev_x86_64.squashfs',
commitment: {
hash: '/6romKTVQGSaOU7FqSZdw0kFyd7P+NBSYNwM3q7Fe44=',
size: 1411657728,
@@ -158,7 +158,7 @@ export namespace Mock {
},
'x86_64-nonfree': {
publishedAt: '2025-04-21T21:15:17.955265284Z',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.0/startos-0.4.0-alpha.0-33ae46f~dev_x86_64-nonfree.squashfs',
url: 'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.1/startos-0.4.0-alpha.1-33ae46f~dev_x86_64-nonfree.squashfs',
commitment: {
hash: 'HCRq9sr/0t85pMdrEgNBeM4x11zVKHszGnD1GDyZbSE=',
size: 1731035136,
@@ -179,27 +179,21 @@ export namespace Mock {
categories: {
bitcoin: {
name: 'Bitcoin',
description: mockDescription,
},
featured: {
name: 'Featured',
description: mockDescription,
},
lightning: {
name: 'Lightning',
description: mockDescription,
},
communications: {
name: 'Communications',
description: mockDescription,
},
data: {
name: 'Data',
description: mockDescription,
},
ai: {
name: 'AI',
description: mockDescription,
},
},
}

View File

@@ -3,6 +3,12 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
import { StartOSDiskInfo, FetchLogsReq, FetchLogsRes } from '@start9labs/shared'
import { IST, T } from '@start9labs/start-sdk'
import { WebSocketSubjectConfig } from 'rxjs/webSocket'
import {
GetPackageReq,
GetPackageRes,
GetPackagesReq,
GetPackagesRes,
} from '@start9labs/marketplace'
export namespace RR {
// websocket
@@ -86,7 +92,7 @@ export namespace RR {
metrics: ServerMetrics
}
export type UpdateServerReq = { registry: string } // server.update
export type UpdateServerReq = { registry: string; targetVersion: string } // server.update
export type UpdateServerRes = 'updating' | 'no-updates'
export type RestartServerReq = {} // server.restart
@@ -362,8 +368,17 @@ export namespace RR {
// registry
/** these are returned in ASCENDING order. the newest available version will be the LAST in the object */
export type CheckOSUpdateReq = { serverId: string }
export type GetRegistryOsUpdateRes = { [version: string]: T.OsVersionInfo }
export type CheckOsUpdateReq = { registry: string; serverId: string }
export type CheckOsUpdateRes = { [version: string]: T.OsVersionInfo }
export type GetRegistryInfoReq = { registry: string }
export type GetRegistryInfoRes = T.RegistryInfo
export type GetRegistryPackageReq = GetPackageReq & { registry: string }
export type GetRegistryPackageRes = GetPackageRes
export type GetRegistryPackagesReq = GetPackagesReq & { registry: string }
export type GetRegistryPackagesRes = GetPackagesRes
}
export type Breakages = {

View File

@@ -1,9 +1,4 @@
import {
GetPackageRes,
GetPackagesRes,
MarketplacePkg,
} from '@start9labs/marketplace'
import { RPCOptions } from '@start9labs/shared'
import { MarketplacePkg } from '@start9labs/marketplace'
import { T } from '@start9labs/start-sdk'
import { RR } from './api.types'
import { WebSocketSubject } from 'rxjs/webSocket'
@@ -113,7 +108,7 @@ export abstract class ApiService {
params: RR.FollowServerMetricsReq,
): Promise<RR.FollowServerMetricsRes>
abstract updateServer(url?: string): Promise<RR.UpdateServerRes>
abstract updateServer(params: RR.UpdateServerReq): Promise<RR.UpdateServerRes>
abstract restartServer(
params: RR.RestartServerReq,
@@ -145,24 +140,21 @@ export abstract class ApiService {
// marketplace URLs
abstract registryRequest<T>(
registryUrl: string,
options: RPCOptions,
): Promise<T>
abstract checkOSUpdate(
qp: RR.CheckOSUpdateReq,
): Promise<RR.GetRegistryOsUpdateRes>
params: RR.CheckOsUpdateReq,
): Promise<RR.CheckOsUpdateRes>
abstract getRegistryInfo(registryUrl: string): Promise<T.RegistryInfo>
abstract getRegistryInfo(
params: RR.GetRegistryInfoReq,
): Promise<RR.GetRegistryInfoRes>
abstract getRegistryPackage(
url: string,
id: string,
versionRange: string | null,
): Promise<GetPackageRes>
params: RR.GetRegistryPackageReq,
): Promise<RR.GetRegistryPackageRes>
abstract getRegistryPackages(registryUrl: string): Promise<GetPackagesRes>
abstract getRegistryPackages(
params: RR.GetRegistryPackagesReq,
): Promise<RR.GetRegistryPackagesRes>
// notification

View File

@@ -10,7 +10,6 @@ import {
import { PATCH_CACHE } from 'src/app/services/patch-db/patch-db-source'
import { ApiService } from './embassy-api.service'
import { RR } from './api.types'
import { ConfigService } from '../config.service'
import { webSocket, WebSocketSubject } from 'rxjs/webSocket'
import { Observable, filter, firstValueFrom } from 'rxjs'
import { AuthService } from '../auth.service'
@@ -18,13 +17,7 @@ import { DOCUMENT } from '@angular/common'
import { DataModel } from '../patch-db/data-model'
import { Dump, pathFromArray } from 'patch-db-client'
import { T } from '@start9labs/start-sdk'
import {
GetPackageReq,
GetPackageRes,
GetPackagesReq,
GetPackagesRes,
MarketplacePkg,
} from '@start9labs/marketplace'
import { MarketplacePkg } from '@start9labs/marketplace'
import { blake3 } from '@noble/hashes/blake3'
@Injectable()
@@ -32,7 +25,6 @@ export class LiveApiService extends ApiService {
constructor(
@Inject(DOCUMENT) private readonly document: Document,
private readonly http: HttpService,
private readonly config: ConfigService,
private readonly auth: AuthService,
@Inject(PATCH_CACHE) private readonly cache$: Observable<Dump<DataModel>>,
) {
@@ -248,10 +240,7 @@ export class LiveApiService extends ApiService {
return this.rpcRequest({ method: 'server.metrics.follow', params })
}
async updateServer(url?: string): Promise<RR.UpdateServerRes> {
const params = {
registry: url || this.config.startosRegistry,
}
async updateServer(params: RR.UpdateServerReq): Promise<RR.UpdateServerRes> {
return this.rpcRequest({ method: 'server.update', params })
}
@@ -283,61 +272,38 @@ export class LiveApiService extends ApiService {
// marketplace URLs
async registryRequest<T>(
registryUrl: string,
options: RPCOptions,
): Promise<T> {
return this.rpcRequest({
...options,
method: `registry.${options.method}`,
params: { registry: registryUrl, ...options.params },
})
}
async checkOSUpdate(
qp: RR.CheckOSUpdateReq,
): Promise<RR.GetRegistryOsUpdateRes> {
const { serverId } = qp
return this.registryRequest(this.config.startosRegistry, {
method: 'os.version.get',
params: { serverId },
})
}
async getRegistryInfo(registryUrl: string): Promise<T.RegistryInfo> {
return this.registryRequest(registryUrl, {
method: 'info',
params: {},
})
}
async getRegistryPackage(
registryUrl: string,
id: string,
versionRange: string | null,
): Promise<GetPackageRes> {
const params: GetPackageReq = {
id,
version: versionRange,
otherVersions: 'short',
}
return this.registryRequest<GetPackageRes>(registryUrl, {
method: 'package.get',
params: RR.CheckOsUpdateReq,
): Promise<RR.CheckOsUpdateRes> {
return this.rpcRequest({
method: 'registry.os.version.get',
params,
})
}
async getRegistryPackages(registryUrl: string): Promise<GetPackagesRes> {
const params: GetPackagesReq = {
id: null,
version: null,
otherVersions: 'short',
}
async getRegistryInfo(
params: RR.GetRegistryInfoReq,
): Promise<RR.GetRegistryInfoRes> {
return this.rpcRequest({
method: 'registry.info',
params,
})
}
return this.registryRequest<GetPackagesRes>(registryUrl, {
method: 'package.get',
async getRegistryPackage(
params: RR.GetRegistryPackageReq,
): Promise<RR.GetRegistryPackageRes> {
return this.rpcRequest({
method: 'registry.package.get',
params,
})
}
async getRegistryPackages(
params: RR.GetRegistryPackagesReq,
): Promise<RR.GetRegistryPackagesRes> {
return this.rpcRequest({
method: 'registry.package.get',
params,
})
}

View File

@@ -169,6 +169,7 @@ export class MockApiService extends ApiService {
pathArr: Array<string | number>,
value: T,
): Promise<RR.SetDBValueRes> {
console.warn(pathArr, value)
const pointer = pathFromArray(pathArr)
const params: RR.SetDBValueReq<T> = { pointer, value }
await pauseFor(2000)
@@ -367,7 +368,7 @@ export class MockApiService extends ApiService {
}
}
async updateServer(url?: string): Promise<RR.UpdateServerRes> {
async updateServer(params?: RR.UpdateServerReq): Promise<RR.UpdateServerRes> {
await pauseFor(2000)
const initialProgress = {
size: null,
@@ -475,41 +476,37 @@ export class MockApiService extends ApiService {
// marketplace URLs
async registryRequest(
registryUrl: string,
options: RPCOptions,
): Promise<any> {
await pauseFor(2000)
return Error('do not call directly')
}
async checkOSUpdate(
qp: RR.CheckOSUpdateReq,
): Promise<RR.GetRegistryOsUpdateRes> {
params: RR.CheckOsUpdateReq,
): Promise<RR.CheckOsUpdateRes> {
await pauseFor(2000)
return Mock.RegistryOSUpdate
}
async getRegistryInfo(registryUrl: string): Promise<T.RegistryInfo> {
async getRegistryInfo(
params: RR.GetRegistryInfoReq,
): Promise<RR.GetRegistryInfoRes> {
await pauseFor(2000)
return Mock.RegistryInfo
}
async getRegistryPackage(
url: string,
id: string,
versionRange: string,
): Promise<GetPackageRes> {
params: RR.GetRegistryPackageReq,
): Promise<RR.GetRegistryPackageRes> {
await pauseFor(2000)
if (!versionRange || versionRange === '=*') {
const { targetVersion, id } = params
if (!targetVersion || targetVersion === '=*') {
return Mock.RegistryPackages[id]!
} else {
return Mock.OtherPackageVersions[id]![versionRange]!
return Mock.OtherPackageVersions[id]![targetVersion]!
}
}
async getRegistryPackages(registryUrl: string): Promise<GetPackagesRes> {
async getRegistryPackages(
params: RR.GetRegistryPackagesReq,
): Promise<RR.GetRegistryPackagesRes> {
await pauseFor(2000)
return Mock.RegistryPackages
}

View File

@@ -6,26 +6,14 @@ const version = require('../../../../../../package.json').version
export const mockPatchData: DataModel = {
ui: {
name: `Matt's Server`,
theme: 'Dark',
marketplace: {
selectedUrl: 'https://registry.start9.com/',
knownHosts: {
'https://registry.start9.com/': {
name: 'Start9 Registry',
},
'https://community-registry.start9.com/': {},
'https://beta-registry.start9.com/': {
name: 'Dark9',
},
},
registries: {
'https://registry.start9.com/': 'Start9 Registry',
'https://community-registry.start9.com/': 'Community Registry',
},
gaming: {
snake: {
highScore: 0,
},
},
language: 'english',
startosRegistry: 'https://registry.start9.com/',
snakeHighScore: 0,
ackInstructions: {},
language: 'english',
},
serverInfo: {
arch: 'x86_64',

View File

@@ -7,7 +7,7 @@ import { PackageDataEntry } from './patch-db/data-model'
const {
gitHash,
useMocks,
ui: { api, marketplace, mocks, startosRegistry },
ui: { api, mocks },
} = require('../../../../../config.json') as WorkspaceConfig
@Injectable({
@@ -26,8 +26,6 @@ export class ConfigService {
mocks = mocks
gitHash = gitHash
api = api
marketplace = marketplace
startosRegistry = startosRegistry
skipStartupAlerts = useMocks && mocks.skipStartupAlerts
supportsWebSockets = !!window.WebSocket

View File

@@ -7,7 +7,7 @@ import {
StoreDataWithUrl,
StoreIdentity,
} from '@start9labs/marketplace'
import { Exver, sameUrl } from '@start9labs/shared'
import { Exver, defaultRegistries, sameUrl } from '@start9labs/shared'
import { T } from '@start9labs/start-sdk'
import { PatchDB } from 'patch-db-client'
import {
@@ -31,32 +31,28 @@ import {
} from 'rxjs'
import { RR } from 'src/app/services/api/api.types'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { DataModel, UIStore } from 'src/app/services/patch-db/data-model'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { ClientStorageService } from './client-storage.service'
import { ConfigService } from './config.service'
const { start9, community } = defaultRegistries
@Injectable({
providedIn: 'root',
})
export class MarketplaceService {
private readonly registryUrlSubject$ = new ReplaySubject<string>(1)
private readonly registryUrl$ = this.registryUrlSubject$.pipe(
private readonly currentRegistryUrlSubject$ = new ReplaySubject<string>(1)
private readonly currentRegistryUrl$ = this.currentRegistryUrlSubject$.pipe(
distinctUntilChanged(),
)
private readonly registry$: Observable<StoreDataWithUrl> =
this.registryUrl$.pipe(
private readonly currentRegistry$: Observable<StoreDataWithUrl> =
this.currentRegistryUrl$.pipe(
switchMap(url => this.fetchRegistry$(url)),
filter(Boolean),
map(registry => {
// @TODO Aiden let's drop description. We do not use it. categories should just be Record<string, string>
registry.info.categories = {
all: {
name: 'All',
description: {
short: 'All registry packages',
long: 'An unfiltered list of all packages available on this registry.',
},
},
...registry.info.categories,
}
@@ -66,36 +62,27 @@ export class MarketplaceService {
shareReplay(1),
)
private readonly knownHosts$: Observable<StoreIdentity[]> = this.patch
.watch$('ui', 'marketplace', 'knownHosts')
private readonly registries$: Observable<StoreIdentity[]> = this.patch
.watch$('ui', 'registries')
.pipe(
map(hosts => {
const { start9, community } = this.config.marketplace
let arr = [
toStoreIdentity(start9, hosts[start9]),
toStoreIdentity(community, {
...hosts[community],
name: 'Community Registry',
}),
]
return arr.concat(
Object.entries(hosts)
.filter(([url, _]) => ![start9, community].includes(url as any))
.map(([url, store]) => toStoreIdentity(url, store)),
)
}),
map(registries => [
toStoreIdentity(start9, registries[start9]),
toStoreIdentity(community, registries[community]),
...Object.entries(registries)
.filter(([url, _]) => ![start9, community].includes(url as any))
.map(([url, name]) => toStoreIdentity(url, name)),
]),
)
private readonly filteredKnownHosts$: Observable<StoreIdentity[]> =
private readonly filteredRegistries$: Observable<StoreIdentity[]> =
combineLatest([
this.clientStorageService.showDevTools$,
this.knownHosts$,
this.registries$,
]).pipe(
map(([devMode, knownHosts]) =>
map(([devMode, registries]) =>
devMode
? knownHosts
: knownHosts.filter(
? registries
: registries.filter(
({ url }) => !url.includes('alpha') && !url.includes('beta'),
),
),
@@ -103,7 +90,7 @@ export class MarketplaceService {
private readonly requestErrors$ = new BehaviorSubject<string[]>([])
readonly marketplace$: Observable<Marketplace> = this.knownHosts$.pipe(
readonly marketplace$: Observable<Marketplace> = this.registries$.pipe(
startWith<StoreIdentity[]>([]),
pairwise(),
mergeMap(([prev, curr]) =>
@@ -112,7 +99,8 @@ export class MarketplaceService {
mergeMap(({ url, name }) =>
this.fetchRegistry$(url).pipe(
tap(data => {
if (data?.info.name) this.updateStoreName(url, name, data.info.name)
if (data?.info.name)
this.updateRegistryName(url, name, data.info.name)
}),
map<StoreData | null, [string, StoreData | null]>(data => [url, data]),
startWith<[string, StoreData | null]>([url, null]),
@@ -132,27 +120,25 @@ export class MarketplaceService {
constructor(
private readonly api: ApiService,
private readonly patch: PatchDB<DataModel>,
private readonly config: ConfigService,
private readonly clientStorageService: ClientStorageService,
private readonly exver: Exver,
) {}
getKnownHosts$(filtered = false): Observable<StoreIdentity[]> {
getRegistries$(filtered = false): Observable<StoreIdentity[]> {
// option to filter out hosts containing 'alpha' or 'beta' substrings in registryURL
return filtered ? this.filteredKnownHosts$ : this.knownHosts$
return filtered ? this.filteredRegistries$ : this.registries$
}
getRegistryUrl$() {
return this.registryUrl$
getCurrentRegistryUrl$() {
return this.currentRegistryUrl$
}
setRegistryUrl(url: string | null) {
const registryUrl = url || this.config.marketplace.start9
this.registryUrlSubject$.next(registryUrl)
setRegistryUrl(url: string) {
this.currentRegistryUrlSubject$.next(url)
}
getRegistry$(): Observable<StoreDataWithUrl> {
return this.registry$
getCurrentRegistry$(): Observable<StoreDataWithUrl> {
return this.currentRegistry$
}
getPackage$(
@@ -161,7 +147,7 @@ export class MarketplaceService {
flavor: string | null,
registryUrl?: string,
): Observable<MarketplacePkg> {
return this.registry$.pipe(
return this.currentRegistry$.pipe(
switchMap(registry => {
const url = registryUrl || registry.url
const pkg = registry.packages.find(
@@ -176,17 +162,12 @@ export class MarketplaceService {
}
fetchInfo$(url: string): Observable<T.RegistryInfo> {
return from(this.api.getRegistryInfo(url)).pipe(
return from(this.api.getRegistryInfo({ registry: url })).pipe(
map(info => ({
...info,
// @TODO Aiden let's drop description. We do not use it. categories should just be Record<string, string>
categories: {
all: {
name: 'All',
description: {
short: '',
long: '',
},
},
...info.categories,
},
@@ -202,7 +183,7 @@ export class MarketplaceService {
}
private fetchRegistry$(url: string): Observable<StoreDataWithUrl | null> {
console.log('FETCHING REGISTRY: ', url)
console.warn('FETCHING REGISTRY: ', url)
return combineLatest([this.fetchInfo$(url), this.fetchPackages$(url)]).pipe(
map(([info, packages]) => ({ info, packages, url })),
catchError(e => {
@@ -214,7 +195,14 @@ export class MarketplaceService {
}
private fetchPackages$(url: string): Observable<MarketplacePkg[]> {
return from(this.api.getRegistryPackages(url)).pipe(
return from(
this.api.getRegistryPackages({
registry: url,
id: null,
targetVersion: null,
otherVersions: 'short',
}),
).pipe(
map(packages => {
return Object.entries(packages).flatMap(([id, pkgInfo]) =>
Object.keys(pkgInfo.best).map(version =>
@@ -237,7 +225,12 @@ export class MarketplaceService {
flavor: string | null,
): Observable<MarketplacePkg> {
return from(
this.api.getRegistryPackage(url, id, version ? `=${version}` : null),
this.api.getRegistryPackage({
registry: url,
id,
targetVersion: version ? `=${version}` : null,
otherVersions: 'short',
}),
).pipe(
map(pkgInfo =>
this.convertRegistryPkgToMarketplacePkg(id, version, flavor, pkgInfo),
@@ -288,23 +281,21 @@ export class MarketplaceService {
await this.api.installPackage(params)
}
private async updateStoreName(
private async updateRegistryName(
url: string,
oldName: string | undefined,
oldName: string | null,
newName: string,
): Promise<void> {
console.warn(oldName, newName)
if (oldName !== newName) {
this.api.setDbValue<string>(
['marketplace', 'knownHosts', url, 'name'],
newName,
)
this.api.setDbValue<string>(['registries', url], newName)
}
}
}
function toStoreIdentity(url: string, uiStore: UIStore): StoreIdentity {
function toStoreIdentity(url: string, name?: string | null): StoreIdentity {
return {
url,
...uiStore,
name: name || url,
}
}

View File

@@ -1,6 +1,12 @@
import { Injectable } from '@angular/core'
import { PatchDB } from 'patch-db-client'
import { BehaviorSubject, distinctUntilChanged, map, combineLatest } from 'rxjs'
import {
BehaviorSubject,
distinctUntilChanged,
map,
combineLatest,
firstValueFrom,
} from 'rxjs'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { getServerInfo } from 'src/app/utils/get-server-info'
import { DataModel } from './patch-db/data-model'
@@ -11,7 +17,7 @@ import { RR } from './api/api.types'
providedIn: 'root',
})
export class OSService {
osUpdate?: RR.GetRegistryOsUpdateRes
osUpdate?: RR.CheckOsUpdateRes
updateAvailable$ = new BehaviorSubject<boolean>(false)
readonly updating$ = this.patch.watch$('serverInfo', 'statusInfo').pipe(
@@ -47,7 +53,12 @@ export class OSService {
async loadOS(): Promise<void> {
const { version, id } = await getServerInfo(this.patch)
this.osUpdate = await this.api.checkOSUpdate({ serverId: id })
const { startosRegistry } = await firstValueFrom(this.patch.watch$('ui'))
this.osUpdate = await this.api.checkOSUpdate({
registry: startosRegistry,
serverId: id,
})
const [latestVersion, _] = Object.entries(this.osUpdate).at(-1)!
const updateAvailable =
Version.parse(latestVersion).compare(Version.parse(version)) === 'greater'

View File

@@ -5,30 +5,13 @@ export type DataModel = T.Public & { ui: UIData; packageData: AllPackageData }
export type UIData = {
name: string | null
marketplace: UIMarketplaceData
gaming: {
snake: {
highScore: number
}
}
registries: Record<string, string | null>
ackInstructions: Record<string, boolean>
theme: string
snakeHighScore: number
startosRegistry: string
language: Languages
}
export type UIMarketplaceData = {
selectedUrl: string
knownHosts: {
'https://registry.start9.com/': UIStore
'https://community-registry.start9.com/': UIStore
[url: string]: UIStore
}
}
export type UIStore = {
name?: string
}
export type NetworkInfo = T.NetworkInfo & {
// @TODO 041
// start9To: {