mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
Feat/combine uis (#2633)
* wip * restructure backend for new ui structure * new patchdb bootstrap, single websocket api, local storage migration, more * update db websocket * init apis * update patch-db * setup progress * feat: implement state service, alert and routing Signed-off-by: waterplea <alexander@inkin.ru> * update setup wizard for new types * feat: add init page Signed-off-by: waterplea <alexander@inkin.ru> * chore: refactor message, patch-db source stream and connection service Signed-off-by: waterplea <alexander@inkin.ru> * fix method not found on state * fix backend bugs * fix compat assets * address comments * remove unneeded styling * cleaner progress * bugfixes * fix init logs * fix progress reporting * fix navigation by getting state after init * remove patch dependency from live api * fix caching * re-add patchDB to live api * fix metrics values * send close frame * add bootId and fix polling --------- Signed-off-by: waterplea <alexander@inkin.ru> Co-authored-by: Aiden McClelland <me@drbonez.dev> Co-authored-by: waterplea <alexander@inkin.ru>
This commit is contained in:
@@ -3,7 +3,6 @@ import {
|
||||
HttpOptions,
|
||||
HttpService,
|
||||
isRpcError,
|
||||
Log,
|
||||
Method,
|
||||
RpcError,
|
||||
RPCOptions,
|
||||
@@ -12,13 +11,12 @@ import { ApiService } from './embassy-api.service'
|
||||
import { RR } from './api.types'
|
||||
import { parsePropertiesPermissive } from 'src/app/util/properties.util'
|
||||
import { ConfigService } from '../config.service'
|
||||
import { webSocket, WebSocketSubjectConfig } from 'rxjs/webSocket'
|
||||
import { webSocket } from 'rxjs/webSocket'
|
||||
import { Observable, filter, firstValueFrom } from 'rxjs'
|
||||
import { AuthService } from '../auth.service'
|
||||
import { DOCUMENT } from '@angular/common'
|
||||
import { DataModel } from '../patch-db/data-model'
|
||||
import { PatchDB, pathFromArray, Update } from 'patch-db-client'
|
||||
import { getServerInfo } from 'src/app/util/get-server-info'
|
||||
import { PatchDB, pathFromArray } from 'patch-db-client'
|
||||
|
||||
@Injectable()
|
||||
export class LiveApiService extends ApiService {
|
||||
@@ -30,10 +28,11 @@ export class LiveApiService extends ApiService {
|
||||
private readonly patch: PatchDB<DataModel>,
|
||||
) {
|
||||
super()
|
||||
;(window as any).rpcClient = this
|
||||
; (window as any).rpcClient = this
|
||||
}
|
||||
|
||||
// for getting static files: ex icons, instructions, licenses
|
||||
|
||||
async getStatic(url: string): Promise<string> {
|
||||
return this.httpRequest({
|
||||
method: Method.GET,
|
||||
@@ -43,6 +42,7 @@ export class LiveApiService extends ApiService {
|
||||
}
|
||||
|
||||
// for sideloading packages
|
||||
|
||||
async uploadPackage(guid: string, body: Blob): Promise<string> {
|
||||
return this.httpRequest({
|
||||
method: Method.POST,
|
||||
@@ -52,8 +52,36 @@ export class LiveApiService extends ApiService {
|
||||
})
|
||||
}
|
||||
|
||||
// websocket
|
||||
|
||||
openWebsocket$<T>(
|
||||
guid: string,
|
||||
config: RR.WebsocketConfig<T>,
|
||||
): Observable<T> {
|
||||
const { location } = this.document.defaultView!
|
||||
const protocol = location.protocol === 'http:' ? 'ws' : 'wss'
|
||||
const host = location.host
|
||||
|
||||
return webSocket({
|
||||
url: `${protocol}://${host}/ws/rpc/${guid}`,
|
||||
...config,
|
||||
})
|
||||
}
|
||||
|
||||
// state
|
||||
|
||||
async getState(): Promise<RR.ServerState> {
|
||||
return this.rpcRequest({ method: 'state', params: {} })
|
||||
}
|
||||
|
||||
// db
|
||||
|
||||
async subscribeToPatchDB(
|
||||
params: RR.SubscribePatchReq,
|
||||
): Promise<RR.SubscribePatchRes> {
|
||||
return this.rpcRequest({ method: 'db.subscribe', params })
|
||||
}
|
||||
|
||||
async setDbValue<T>(
|
||||
pathArr: Array<string | number>,
|
||||
value: T,
|
||||
@@ -87,29 +115,57 @@ export class LiveApiService extends ApiService {
|
||||
return this.rpcRequest({ method: 'auth.reset-password', params })
|
||||
}
|
||||
|
||||
// diagnostic
|
||||
|
||||
async diagnosticGetError(): Promise<RR.DiagnosticErrorRes> {
|
||||
return this.rpcRequest<RR.DiagnosticErrorRes>({
|
||||
method: 'diagnostic.error',
|
||||
params: {},
|
||||
})
|
||||
}
|
||||
|
||||
async diagnosticRestart(): Promise<void> {
|
||||
return this.rpcRequest<void>({
|
||||
method: 'diagnostic.restart',
|
||||
params: {},
|
||||
})
|
||||
}
|
||||
|
||||
async diagnosticForgetDrive(): Promise<void> {
|
||||
return this.rpcRequest<void>({
|
||||
method: 'diagnostic.disk.forget',
|
||||
params: {},
|
||||
})
|
||||
}
|
||||
|
||||
async diagnosticRepairDisk(): Promise<void> {
|
||||
return this.rpcRequest<void>({
|
||||
method: 'diagnostic.disk.repair',
|
||||
params: {},
|
||||
})
|
||||
}
|
||||
|
||||
async diagnosticGetLogs(
|
||||
params: RR.GetServerLogsReq,
|
||||
): Promise<RR.GetServerLogsRes> {
|
||||
return this.rpcRequest<RR.GetServerLogsRes>({
|
||||
method: 'diagnostic.logs',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
// init
|
||||
|
||||
async initGetProgress(): Promise<RR.InitGetProgressRes> {
|
||||
return this.rpcRequest({ method: 'init.subscribe', params: {} })
|
||||
}
|
||||
|
||||
async initFollowLogs(): Promise<RR.FollowServerLogsRes> {
|
||||
return this.rpcRequest({ method: 'init.logs.follow', params: {} })
|
||||
}
|
||||
|
||||
// server
|
||||
|
||||
async echo(params: RR.EchoReq, urlOverride?: string): Promise<RR.EchoRes> {
|
||||
return this.rpcRequest({ method: 'echo', params }, urlOverride)
|
||||
}
|
||||
|
||||
openPatchWebsocket$(): Observable<Update<DataModel>> {
|
||||
const config: WebSocketSubjectConfig<Update<DataModel>> = {
|
||||
url: `/db`,
|
||||
closeObserver: {
|
||||
next: val => {
|
||||
if (val.reason === 'UNAUTHORIZED') this.auth.setUnverified()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return this.openWebsocket(config)
|
||||
}
|
||||
|
||||
openLogsWebsocket$(config: WebSocketSubjectConfig<Log>): Observable<Log> {
|
||||
return this.openWebsocket(config)
|
||||
}
|
||||
|
||||
async getSystemTime(
|
||||
params: RR.GetSystemTimeReq,
|
||||
): Promise<RR.GetSystemTimeRes> {
|
||||
@@ -175,12 +231,6 @@ export class LiveApiService extends ApiService {
|
||||
return this.rpcRequest({ method: 'server.shutdown', params })
|
||||
}
|
||||
|
||||
async systemRebuild(
|
||||
params: RR.RestartServerReq,
|
||||
): Promise<RR.RestartServerRes> {
|
||||
return this.rpcRequest({ method: 'server.rebuild', params })
|
||||
}
|
||||
|
||||
async repairDisk(params: RR.RestartServerReq): Promise<RR.RestartServerRes> {
|
||||
return this.rpcRequest({ method: 'disk.repair', params })
|
||||
}
|
||||
@@ -203,10 +253,7 @@ export class LiveApiService extends ApiService {
|
||||
})
|
||||
}
|
||||
|
||||
async getEos(): Promise<RR.GetMarketplaceEosRes> {
|
||||
const { id } = await getServerInfo(this.patch)
|
||||
const qp: RR.GetMarketplaceEosReq = { serverId: id }
|
||||
|
||||
async checkOSUpdate(qp: RR.CheckOSUpdateReq): Promise<RR.CheckOSUpdateRes> {
|
||||
return this.marketplaceProxy(
|
||||
'/eos/v0/latest',
|
||||
qp,
|
||||
@@ -417,16 +464,6 @@ export class LiveApiService extends ApiService {
|
||||
})
|
||||
}
|
||||
|
||||
private openWebsocket<T>(config: WebSocketSubjectConfig<T>): Observable<T> {
|
||||
const { location } = this.document.defaultView!
|
||||
const protocol = location.protocol === 'http:' ? 'ws' : 'wss'
|
||||
const host = location.host
|
||||
|
||||
config.url = `${protocol}://${host}/ws${config.url}`
|
||||
|
||||
return webSocket(config)
|
||||
}
|
||||
|
||||
private async rpcRequest<T>(
|
||||
options: RPCOptions,
|
||||
urlOverride?: string,
|
||||
@@ -445,9 +482,7 @@ export class LiveApiService extends ApiService {
|
||||
const patchSequence = res.headers.get('x-patch-sequence')
|
||||
if (patchSequence)
|
||||
await firstValueFrom(
|
||||
this.patch.cache$.pipe(
|
||||
filter(({ sequence }) => sequence >= Number(patchSequence)),
|
||||
),
|
||||
this.patch.cache$.pipe(filter(({ id }) => id >= Number(patchSequence))),
|
||||
)
|
||||
|
||||
return body.result
|
||||
|
||||
Reference in New Issue
Block a user