mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
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:
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user