export patchdb ts types from rust

This commit is contained in:
Aiden McClelland
2024-03-27 17:47:12 -06:00
parent 9cf62f03fa
commit f41f5ebebd
75 changed files with 536 additions and 634 deletions

View File

@@ -18,7 +18,7 @@ import {
} from 'rxjs'
import { AbstractMarketplaceService } from '@start9labs/marketplace'
import { MarketplaceService } from 'src/app/services/marketplace.service'
import { DataModel, PackageState } from 'src/app/services/patch-db/data-model'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { SplitPaneTracker } from 'src/app/services/split-pane.service'
import { Emver, THEME } from '@start9labs/shared'
import { ConnectionService } from 'src/app/services/connection.service'
@@ -77,12 +77,10 @@ export class MenuComponent {
filter(([prev, curr]) =>
Object.values(prev).some(
p =>
[
PackageState.Installing,
PackageState.Updating,
PackageState.Restoring,
].includes(p.stateInfo.state) &&
[PackageState.Installed, PackageState.Removing].includes(
['installing', 'updating', 'restoring'].includes(
p.stateInfo.state,
) &&
['installed', 'removing'].includes(
curr[getManifest(p).id].stateInfo.state,
),
),

View File

@@ -1,7 +1,7 @@
import { Component } from '@angular/core'
import { ModalController } from '@ionic/angular'
import { map, take } from 'rxjs/operators'
import { DataModel, PackageState } from 'src/app/services/patch-db/data-model'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { PatchDB } from 'patch-db-client'
import { firstValueFrom } from 'rxjs'
import { getManifest } from 'src/app/util/get-package-data'
@@ -38,7 +38,7 @@ export class BackupSelectPage {
id,
title,
icon: pkg.icon,
disabled: pkg.stateInfo.state !== PackageState.Installed,
disabled: pkg.stateInfo.state !== 'installed',
checked: false,
}
})

View File

@@ -11,8 +11,6 @@ import { PatchDB } from 'patch-db-client'
import {
DataModel,
PackageDataEntry,
PackageMainStatus,
Status,
} from 'src/app/services/patch-db/data-model'
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
import { isEmptyObject, ErrorToastService, getPkgId } from '@start9labs/shared'
@@ -20,6 +18,7 @@ import { ActionSuccessPage } from 'src/app/modals/action-success/action-success.
import { hasCurrentDeps } from 'src/app/util/has-deps'
import { getAllPackages, getManifest } from 'src/app/util/get-package-data'
import { ActionMetadata } from '@start9labs/start-sdk/cjs/sdk/lib/types'
import { Status } from '../../../../../../../../core/startos/bindings/Status'
@Component({
selector: 'app-actions',

View File

@@ -8,9 +8,8 @@ import { PatchDB } from 'patch-db-client'
import { QRComponent } from 'src/app/components/qr/qr.component'
import { map } from 'rxjs'
import { types as T } from '@start9labs/start-sdk'
type ServiceInterface = T.ServiceInterface
type ServiceInterfaceWithHostInfo = T.ServiceInterfaceWithHostInfo
import { ServiceInterface } from '../../../../../../../../core/startos/bindings/ServiceInterface'
import { ServiceInterfaceWithHostInfo } from '../../../../../../../../core/startos/bindings/ServiceInterfaceWithHostInfo'
type MappedInterface = ServiceInterface & {
addresses: MappedAddress[]
@@ -109,12 +108,10 @@ function getAddresses(
const username = addressInfo.username ? addressInfo.username + '@' : ''
const suffix = addressInfo.suffix || ''
const hostnames =
host.kind === 'multi'
? host.hostnames
: host.hostname
const hostnames = host.kind === 'multi' ? host.hostnames : [] // TODO: non-multi
/* host.hostname
? [host.hostname]
: []
: [] */
const addresses: MappedAddress[] = []

View File

@@ -1,11 +1,8 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import {
MainStatus,
PackageDataEntry,
PackageMainStatus,
} from 'src/app/services/patch-db/data-model'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
import { PkgInfo } from 'src/app/util/get-package-info'
import { UiLauncherService } from 'src/app/services/ui-launcher.service'
import { MainStatus } from '../../../../../../../../../core/startos/bindings/MainStatus'
@Component({
selector: 'app-list-pkg',
@@ -21,13 +18,13 @@ export class AppListPkgComponent {
get pkgMainStatus(): MainStatus {
return (
this.pkg.entry.status.main || {
status: PackageMainStatus.Stopped,
status: 'stopped',
}
)
}
get sigtermTimeout(): string | null {
return this.pkgMainStatus.status === PackageMainStatus.Stopping
return this.pkgMainStatus.status === 'stopping'
? this.pkgMainStatus.timeout
: null
}

View File

@@ -11,10 +11,7 @@ import {
import { PackageProperties } from 'src/app/util/properties.util'
import { QRComponent } from 'src/app/components/qr/qr.component'
import { PatchDB } from 'patch-db-client'
import {
DataModel,
PackageMainStatus,
} from 'src/app/services/patch-db/data-model'
import { DataModel } from 'src/app/services/patch-db/data-model'
import {
ErrorToastService,
getPkgId,
@@ -42,7 +39,7 @@ export class AppPropertiesPage {
stopped$ = this.patch
.watch$('packageData', this.pkgId, 'status', 'main', 'status')
.pipe(map(status => status === PackageMainStatus.Stopped))
.pipe(map(status => status === 'stopped'))
@ViewChild(IonBackButtonDelegate, { static: false })
backButton?: IonBackButtonDelegate

View File

@@ -26,7 +26,7 @@ import {
isRestoring,
isUpdating,
} from 'src/app/util/get-package-data'
import { Manifest } from '@start9labs/marketplace'
import { Manifest } from '../../../../../../../../core/startos/bindings/Manifest'
export interface DependencyInfo {
id: string

View File

@@ -3,7 +3,7 @@ import { ModalController, ToastController } from '@ionic/angular'
import { copyToClipboard, MarkdownComponent } from '@start9labs/shared'
import { from } from 'rxjs'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { Manifest } from '@start9labs/marketplace'
import { Manifest } from '../../../../../../../../../../core/startos/bindings/Manifest'
@Component({
selector: 'app-show-additional',

View File

@@ -1,11 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { ConnectionService } from 'src/app/services/connection.service'
import {
HealthCheckResult,
HealthResult,
MainStatus,
} from 'src/app/services/patch-db/data-model'
import { Manifest } from '@start9labs/marketplace'
import { HealthCheckResult } from '../../../../../../../../../../core/startos/bindings/HealthCheckResult'
@Component({
selector: 'app-show-health-checks',
@@ -21,12 +16,12 @@ export class AppShowHealthChecksComponent {
constructor(private readonly connectionService: ConnectionService) {}
isLoading(result: HealthResult): boolean {
return result === HealthResult.Starting || result === HealthResult.Loading
isLoading(result: HealthCheckResult['result']): boolean {
return result === 'starting' || result === 'loading'
}
isReady(result: HealthResult): boolean {
return result !== HealthResult.Failure && result !== HealthResult.Loading
isReady(result: HealthCheckResult['result']): boolean {
return result !== 'failure' && result !== 'loading'
}
asIsOrder() {

View File

@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { FullProgress } from 'src/app/services/patch-db/data-model'
import { FullProgress } from '../../../../../../../../../../core/startos/bindings/FullProgress'
@Component({
selector: 'app-show-progress',

View File

@@ -8,8 +8,6 @@ import {
import {
DataModel,
PackageDataEntry,
PackageMainStatus,
Status,
} from 'src/app/services/patch-db/data-model'
import { ErrorToastService } from '@start9labs/shared'
import { AlertController, LoadingController } from '@ionic/angular'
@@ -22,8 +20,9 @@ import {
getManifest,
getAllPackages,
} from 'src/app/util/get-package-data'
import { Manifest } from '@start9labs/marketplace'
import { PatchDB } from 'patch-db-client'
import { Status } from '../../../../../../../../../../core/startos/bindings/Status'
import { Manifest } from '../../../../../../../../../../core/startos/bindings/Manifest'
@Component({
selector: 'app-show-status',
@@ -84,7 +83,7 @@ export class AppShowStatusComponent {
}
get sigtermTimeout(): string | null {
return this.pkgStatus?.main.status === PackageMainStatus.Stopping
return this.pkgStatus?.main.status === 'stopping'
? this.pkgStatus.main.timeout
: null
}

View File

@@ -1,20 +1,20 @@
import { Pipe, PipeTransform } from '@angular/core'
import { HealthResult } from 'src/app/services/patch-db/data-model'
import { HealthCheckResult } from '../../../../../../../../../core/startos/bindings/HealthCheckResult'
@Pipe({
name: 'healthColor',
})
export class HealthColorPipe implements PipeTransform {
transform(val: HealthResult): string {
transform(val: HealthCheckResult['result']): string {
switch (val) {
case HealthResult.Success:
case 'success':
return 'success'
case HealthResult.Failure:
case 'failure':
return 'warning'
case HealthResult.Disabled:
case 'disabled':
return 'dark'
case HealthResult.Starting:
case HealthResult.Loading:
case 'starting':
case 'loading':
return 'primary'
}
}

View File

@@ -11,7 +11,7 @@ import { ModalService } from 'src/app/services/modal.service'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { from, map, Observable } from 'rxjs'
import { PatchDB } from 'patch-db-client'
import { Manifest } from '@start9labs/marketplace'
import { Manifest } from '../../../../../../../../../core/startos/bindings/Manifest'
export interface Button {
title: string

View File

@@ -1,14 +1,11 @@
import { Pipe, PipeTransform } from '@angular/core'
import {
DataModel,
HealthCheckResult,
PackageMainStatus,
} from 'src/app/services/patch-db/data-model'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { isEmptyObject } from '@start9labs/shared'
import { map, startWith } from 'rxjs/operators'
import { PatchDB } from 'patch-db-client'
import { Observable } from 'rxjs'
import { Manifest } from '@start9labs/marketplace'
import { HealthCheckResult } from '../../../../../../../../../core/startos/bindings/HealthCheckResult'
import { Manifest } from '../../../../../../../../../core/startos/bindings/Manifest'
@Pipe({
name: 'toHealthChecks',
@@ -21,8 +18,7 @@ export class ToHealthChecksPipe implements PipeTransform {
): Observable<Record<string, HealthCheckResult | null> | null> {
return this.patch.watch$('packageData', manifest.id, 'status', 'main').pipe(
map(main => {
return main.status === PackageMainStatus.Running &&
!isEmptyObject(main.health)
return main.status === 'running' && !isEmptyObject(main.health)
? main.health
: null
}),

View File

@@ -7,7 +7,6 @@ import {
import { AlertController, LoadingController } from '@ionic/angular'
import {
AbstractMarketplaceService,
Manifest,
MarketplacePkg,
} from '@start9labs/marketplace'
import {

View File

@@ -35,7 +35,7 @@
>
<!-- active -->
<ion-note
*ngIf="pkgStatus === 'backing-up'; else queued"
*ngIf="pkgStatus === 'backingUp'; else queued"
class="inline"
slot="end"
>

View File

@@ -6,11 +6,9 @@ import {
} from '@angular/core'
import { PatchDB } from 'patch-db-client'
import { take } from 'rxjs/operators'
import {
DataModel,
PackageMainStatus,
} from 'src/app/services/patch-db/data-model'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { Observable } from 'rxjs'
import { MainStatus } from '../../../../../../../../../core/startos/bindings/MainStatus'
@Component({
selector: 'backing-up',
@@ -32,7 +30,7 @@ export class BackingUpComponent {
name: 'pkgMainStatus',
})
export class PkgMainStatusPipe implements PipeTransform {
transform(pkgId: string): Observable<PackageMainStatus> {
transform(pkgId: string): Observable<MainStatus['status']> {
return this.patch.watch$('packageData', pkgId, 'status', 'main', 'status')
}

View File

@@ -4,7 +4,7 @@ import { ApiService } from 'src/app/services/api/embassy-api.service'
import { ConfigService } from 'src/app/services/config.service'
import cbor from 'cbor'
import { ErrorToastService } from '@start9labs/shared'
import { Manifest } from '@start9labs/marketplace'
import { Manifest } from '../../../../../../../../core/startos/bindings/Manifest'
interface Positions {
[key: string]: [bigint, bigint] // [position, length]

View File

@@ -10,7 +10,6 @@ import { MarketplaceService } from 'src/app/services/marketplace.service'
import {
AbstractMarketplaceService,
Marketplace,
Manifest,
MarketplacePkg,
StoreIdentity,
} from '@start9labs/marketplace'
@@ -25,6 +24,7 @@ import {
isUpdating,
} from 'src/app/util/get-package-data'
import { dryUpdate } from 'src/app/util/dry-update'
import { Manifest } from '../../../../../../../core/startos/bindings/Manifest'
interface UpdatesData {
hosts: StoreIdentity[]

View File

@@ -1,5 +1,5 @@
import { Pipe, PipeTransform } from '@angular/core'
import { Progress } from 'src/app/services/patch-db/data-model'
import { Progress } from '../../../../../../../core/startos/bindings/Progress'
@Pipe({
name: 'installingProgressString',

View File

@@ -1,9 +1,7 @@
import { Pipe, PipeTransform } from '@angular/core'
import {
PackageMainStatus,
PackageState,
} from 'src/app/services/patch-db/data-model'
import { ConfigService } from '../../services/config.service'
import { PackageState } from '../../../../../../../core/startos/bindings/PackageState'
import { MainStatus } from '../../../../../../../core/startos/bindings/MainStatus'
@Pipe({
name: 'isLaunchable',
@@ -11,7 +9,10 @@ import { ConfigService } from '../../services/config.service'
export class LaunchablePipe implements PipeTransform {
constructor(private configService: ConfigService) {}
transform(state: PackageState, status: PackageMainStatus): boolean {
transform(
state: PackageState['state'],
status: MainStatus['status'],
): boolean {
return this.configService.isLaunchable(state, status)
}
}

View File

@@ -2,7 +2,7 @@ import { Pipe, PipeTransform } from '@angular/core'
import { PackageDataEntry } from '../../services/patch-db/data-model'
import { hasUi } from '../../services/config.service'
import { getManifest } from 'src/app/util/get-package-data'
import { Manifest } from '@start9labs/marketplace'
import { Manifest } from '../../../../../../../core/startos/bindings/Manifest'
@Pipe({
name: 'hasUi',

View File

@@ -1,21 +1,16 @@
import {
InstalledState,
PackageDataEntry,
PackageMainStatus,
PackageState,
ServerStatusInfo,
} from 'src/app/services/patch-db/data-model'
import { Metric, NotificationLevel, RR, ServerNotifications } from './api.types'
import { BTC_ICON, LND_ICON, PROXY_ICON } from './api-icons'
import {
DependencyMetadata,
Manifest,
MarketplacePkg,
} from '@start9labs/marketplace'
import { DependencyMetadata, MarketplacePkg } from '@start9labs/marketplace'
import { Log } from '@start9labs/shared'
import { ServerStatus } from '../../../../../../../core/startos/bindings/ServerStatus'
import { Manifest } from '../../../../../../../core/startos/bindings/Manifest'
export module Mock {
export const ServerUpdated: ServerStatusInfo = {
export const ServerUpdated: ServerStatus = {
backupProgress: null,
updateProgress: null,
updated: true,
@@ -75,16 +70,26 @@ export module Mock {
osVersion: '0.2.12',
dependencies: {},
hasConfig: true,
images: ['main'],
assets: [],
volumes: ['main'],
hardwareRequirements: {
device: {},
arch: null,
ram: null,
},
}
export const MockManifestLnd: Manifest = {
id: 'lnd',
title: 'Lightning Network Daemon',
version: '0.11.1',
gitHash: 'abcdefgh',
description: {
short: 'A bolt spec compliant client.',
long: 'More info about LND. More info about LND. More info about LND.',
},
replaces: ['banks', 'governments'],
releaseNotes: 'Dual funded channels!',
license: 'MIT',
wrapperRepo: 'https://github.com/start9labs/lnd-wrapper',
@@ -113,6 +118,14 @@ export module Mock {
},
},
hasConfig: true,
images: ['main'],
assets: [],
volumes: ['main'],
hardwareRequirements: {
device: {},
arch: null,
ram: null,
},
}
export const MockManifestBitcoinProxy: Manifest = {
@@ -145,7 +158,16 @@ export module Mock {
optional: false,
},
},
replaces: [],
hasConfig: false,
images: ['main'],
assets: [],
volumes: ['main'],
hardwareRequirements: {
device: {},
arch: null,
ram: null,
},
}
export const BitcoinDep: DependencyMetadata = {
@@ -1376,7 +1398,7 @@ export module Mock {
export const bitcoind: PackageDataEntry<InstalledState> = {
stateInfo: {
state: PackageState.Installed,
state: 'installed',
manifest: MockManifestBitcoind,
},
icon: '/assets/img/service-icons/bitcoind.svg',
@@ -1384,7 +1406,7 @@ export module Mock {
status: {
configured: true,
main: {
status: PackageMainStatus.Running,
status: 'running',
started: new Date().toISOString(),
health: {},
},
@@ -1408,9 +1430,10 @@ export module Mock {
scheme: 'http',
preferredExternalPort: 80,
addSsl: {
addXForwardedHeaders: false,
// addXForwardedHeaders: false,
preferredExternalPort: 443,
scheme: 'https',
alpn: { specified: ['http/1.1', 'h2'] },
},
secure: null,
},
@@ -1480,9 +1503,10 @@ export module Mock {
scheme: 'http',
preferredExternalPort: 80,
addSsl: {
addXForwardedHeaders: false,
// addXForwardedHeaders: false,
preferredExternalPort: 443,
scheme: 'https',
alpn: { specified: ['http/1.1'] },
},
secure: null,
},
@@ -1608,13 +1632,15 @@ export module Mock {
},
},
currentDependencies: {},
hosts: {},
storeExposedDependents: [],
marketplaceUrl: 'https://registry.start9.com/',
developerKey: 'developer-key',
}
export const bitcoinProxy: PackageDataEntry<InstalledState> = {
stateInfo: {
state: PackageState.Installed,
state: 'installed',
manifest: MockManifestBitcoinProxy,
},
icon: '/assets/img/service-icons/btc-rpc-proxy.png',
@@ -1622,7 +1648,7 @@ export module Mock {
status: {
configured: false,
main: {
status: PackageMainStatus.Stopped,
status: 'stopped',
},
dependencyConfigErrors: {},
},
@@ -1643,9 +1669,10 @@ export module Mock {
scheme: 'http',
preferredExternalPort: 80,
addSsl: {
addXForwardedHeaders: false,
// addXForwardedHeaders: false,
preferredExternalPort: 443,
scheme: 'https',
alpn: { specified: ['http/1.1', 'h2'] },
},
secure: {
ssl: true,
@@ -1745,13 +1772,15 @@ export module Mock {
healthChecks: [],
},
},
hosts: {},
storeExposedDependents: [],
marketplaceUrl: 'https://registry.start9.com/',
developerKey: 'developer-key',
}
export const lnd: PackageDataEntry<InstalledState> = {
stateInfo: {
state: PackageState.Installed,
state: 'installed',
manifest: MockManifestLnd,
},
icon: '/assets/img/service-icons/lnd.png',
@@ -1759,7 +1788,7 @@ export module Mock {
status: {
configured: true,
main: {
status: PackageMainStatus.Stopped,
status: 'stopped',
},
dependencyConfigErrors: {
'btc-rpc-proxy': 'Username not found',
@@ -1993,9 +2022,10 @@ export module Mock {
kind: 'exists',
registryUrl: 'https://community-registry.start9.com',
versionSpec: '>2.0.0', // @TODO
healthChecks: [],
},
},
hosts: {},
storeExposedDependents: [],
marketplaceUrl: 'https://registry.start9.com/',
developerKey: 'developer-key',
}

View File

@@ -1,12 +1,11 @@
import { Dump, Revision } from 'patch-db-client'
import { Manifest, MarketplacePkg, StoreInfo } from '@start9labs/marketplace'
import { MarketplacePkg, StoreInfo } from '@start9labs/marketplace'
import { PackagePropertiesVersioned } from 'src/app/util/properties.util'
import { ConfigSpec } from 'src/app/pkg-config/config-types'
import {
DataModel,
HealthCheckResult,
} from 'src/app/services/patch-db/data-model'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { StartOSDiskInfo, LogsRes, ServerLogsReq } from '@start9labs/shared'
import { HealthCheckResult } from '../../../../../../../core/startos/bindings/HealthCheckResult'
import { Manifest } from '../../../../../../../core/startos/bindings/Manifest'
export module RR {
// DB

View File

@@ -10,12 +10,8 @@ import {
} from 'patch-db-client'
import {
DataModel,
FullProgress,
InstallingState,
PackageDataEntry,
PackageMainStatus,
PackageState,
ServerStatus,
StateInfo,
UpdatingState,
} from 'src/app/services/patch-db/data-model'
@@ -41,6 +37,8 @@ import { WebSocketSubjectConfig } from 'rxjs/webSocket'
import { AuthService } from '../auth.service'
import { ConnectionService } from '../connection.service'
import { StoreInfo } from '@start9labs/marketplace'
import { FullProgress } from '../../../../../../../core/startos/bindings/FullProgress'
import { ServerStatus } from '../../../../../../../core/startos/bindings/ServerStatus'
const PROGRESS: FullProgress = {
overall: {
@@ -576,7 +574,7 @@ export class MockApiService extends ApiService {
{
op: PatchOp.REPLACE,
path: appPath,
value: PackageMainStatus.BackingUp,
value: 'backingUp',
},
]
this.mockRevision(appPatch)
@@ -586,7 +584,7 @@ export class MockApiService extends ApiService {
this.mockRevision([
{
...appPatch[0],
value: PackageMainStatus.Stopped,
value: 'stopped',
},
])
this.mockRevision([
@@ -692,7 +690,7 @@ export class MockApiService extends ApiService {
// state: PackageState.Installing,
// if updating
state: PackageState.Updating,
state: 'updating',
manifest: mockPatchData.packageData[params.id].stateInfo.manifest!,
// both
@@ -757,7 +755,7 @@ export class MockApiService extends ApiService {
value: {
...Mock.LocalPkgs[id],
stateInfo: {
state: PackageState.Restoring,
state: 'restoring',
installingInfo: {
newManifest: Mock.LocalPkgs[id].stateInfo.manifest!,
progress: PROGRESS,
@@ -789,7 +787,7 @@ export class MockApiService extends ApiService {
{
op: PatchOp.REPLACE,
path: path + '/status',
value: PackageMainStatus.Running,
value: 'running',
},
{
op: PatchOp.REPLACE,
@@ -849,7 +847,7 @@ export class MockApiService extends ApiService {
{
op: PatchOp.REPLACE,
path: path + '/status',
value: PackageMainStatus.Starting,
value: 'starting',
},
]
@@ -870,7 +868,7 @@ export class MockApiService extends ApiService {
{
op: PatchOp.REPLACE,
path: path + '/status',
value: PackageMainStatus.Starting,
value: 'starting',
},
{
op: PatchOp.ADD,
@@ -886,7 +884,7 @@ export class MockApiService extends ApiService {
{
op: PatchOp.REPLACE,
path: path + '/status',
value: PackageMainStatus.Running,
value: 'running',
},
{
op: PatchOp.REMOVE,
@@ -923,7 +921,7 @@ export class MockApiService extends ApiService {
{
op: PatchOp.REPLACE,
path: path + '/status',
value: PackageMainStatus.Restarting,
value: 'restarting',
},
{
op: PatchOp.REPLACE,
@@ -947,7 +945,7 @@ export class MockApiService extends ApiService {
op: PatchOp.REPLACE,
path: path,
value: {
status: PackageMainStatus.Stopped,
status: 'stopped',
},
},
]
@@ -959,7 +957,7 @@ export class MockApiService extends ApiService {
op: PatchOp.REPLACE,
path: path,
value: {
status: PackageMainStatus.Stopping,
status: 'stopping',
timeout: '35s',
},
},
@@ -989,7 +987,7 @@ export class MockApiService extends ApiService {
{
op: PatchOp.REPLACE,
path: `/packageData/${params.id}/stateInfo/state`,
value: PackageState.Removing,
value: 'removing',
},
]
@@ -1105,7 +1103,7 @@ export class MockApiService extends ApiService {
op: PatchOp.REPLACE,
path: `/packageData/${id}/stateInfo`,
value: {
state: PackageState.Installed,
state: 'installed',
manifest: Mock.LocalPkgs[id].stateInfo.manifest,
},
},
@@ -1149,11 +1147,11 @@ export class MockApiService extends ApiService {
this.mockRevision(patch2)
setTimeout(async () => {
const patch3: Operation<ServerStatus>[] = [
const patch3: Operation<boolean>[] = [
{
op: PatchOp.REPLACE,
path: '/serverInfo/status',
value: ServerStatus.Updated,
path: '/serverInfo/statusInfo/updated',
value: true,
},
{
op: PatchOp.REMOVE,
@@ -1167,7 +1165,7 @@ export class MockApiService extends ApiService {
{
op: PatchOp.REPLACE,
path: '/serverInfo/status',
value: ServerStatus.Running,
value: 'running',
},
]
this.mockRevision(patch4)

View File

@@ -1,9 +1,4 @@
import {
DataModel,
HealthResult,
PackageMainStatus,
PackageState,
} from 'src/app/services/patch-db/data-model'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { Mock } from './api.fixures'
import { BUILT_IN_WIDGETS } from '../../pages/widgets/built-in/widgets'
@@ -39,6 +34,8 @@ export const mockPatchData: DataModel = {
ackInstructions: {},
},
serverInfo: {
arch: 'x86_64',
onionAddress: 'myveryownspecialtoraddress',
id: 'abcdefgh',
version: '0.3.5.1',
lastBackup: new Date(new Date().valueOf() - 604800001).toISOString(),
@@ -47,11 +44,15 @@ export const mockPatchData: DataModel = {
ipInfo: {
eth0: {
ipv4: '10.0.0.1',
ipv4Range: '10.0.0.1/24',
ipv6: null,
ipv6Range: null,
},
wlan0: {
ipv4: '10.0.90.12',
ipv4Range: '10.0.90.12/24',
ipv6: 'FE80:CD00:0000:0CDE:1257:0000:211E:729CD',
ipv6Range: 'FE80:CD00:0000:0CDE:1257:0000:211E:729CD/64',
},
},
lastWifiRegion: null,
@@ -72,11 +73,18 @@ export const mockPatchData: DataModel = {
caFingerprint: 'SHA-256: 63 2B 11 99 44 40 17 DF 37 FC C3 DF 0F 3D 15',
ntpSynced: false,
platform: 'x86_64-nonfree',
zram: true,
governor: 'performance',
wifi: {
ssids: [],
selected: null,
connected: null,
},
},
packageData: {
bitcoind: {
stateInfo: {
state: PackageState.Installed,
state: 'installed',
manifest: {
...Mock.MockManifestBitcoind,
version: '0.20.0',
@@ -87,31 +95,31 @@ export const mockPatchData: DataModel = {
status: {
configured: true,
main: {
status: PackageMainStatus.Running,
status: 'running',
started: '2021-06-14T20:49:17.774Z',
health: {
'ephemeral-health-check': {
name: 'Ephemeral Health Check',
result: HealthResult.Starting,
result: 'starting',
},
'chain-state': {
name: 'Chain State',
result: HealthResult.Loading,
result: 'loading',
message: 'Bitcoin is syncing from genesis',
},
'p2p-interface': {
name: 'P2P',
result: HealthResult.Success,
result: 'success',
message: 'Health check successful',
},
'rpc-interface': {
name: 'RPC',
result: HealthResult.Failure,
result: 'failure',
message: 'RPC interface unreachable.',
},
'unnecessary-health-check': {
name: 'Unnecessary Health Check',
result: HealthResult.Disabled,
result: 'disabled',
},
},
},
@@ -135,9 +143,10 @@ export const mockPatchData: DataModel = {
scheme: 'http',
preferredExternalPort: 80,
addSsl: {
addXForwardedHeaders: false,
// addXForwardedHeaders: false,
preferredExternalPort: 443,
scheme: 'https',
alpn: { specified: ['http/1.1', 'h2'] },
},
secure: null,
},
@@ -207,9 +216,10 @@ export const mockPatchData: DataModel = {
scheme: 'http',
preferredExternalPort: 80,
addSsl: {
addXForwardedHeaders: false,
// addXForwardedHeaders: false,
preferredExternalPort: 443,
scheme: 'https',
alpn: { specified: ['http/1.1'] },
},
secure: null,
},
@@ -335,12 +345,14 @@ export const mockPatchData: DataModel = {
},
},
currentDependencies: {},
hosts: {},
storeExposedDependents: [],
marketplaceUrl: 'https://registry.start9.com/',
developerKey: 'developer-key',
},
lnd: {
stateInfo: {
state: PackageState.Installed,
state: 'installed',
manifest: {
...Mock.MockManifestLnd,
version: '0.11.0',
@@ -351,7 +363,7 @@ export const mockPatchData: DataModel = {
status: {
configured: true,
main: {
status: PackageMainStatus.Stopped,
status: 'stopped',
},
dependencyConfigErrors: {
'btc-rpc-proxy': 'This is a config unsatisfied error',
@@ -586,6 +598,8 @@ export const mockPatchData: DataModel = {
healthChecks: [],
},
},
hosts: {},
storeExposedDependents: [],
marketplaceUrl: 'https://registry.start9.com/',
developerKey: 'developer-key',
},

View File

@@ -2,14 +2,12 @@ import { DOCUMENT } from '@angular/common'
import { Inject, Injectable } from '@angular/core'
import { WorkspaceConfig } from '@start9labs/shared'
import { types } from '@start9labs/start-sdk'
import {
PackageDataEntry,
PackageMainStatus,
PackageState,
} from 'src/app/services/patch-db/data-model'
type HostnameInfoIp = types.HostnameInfoIp
type HostnameInfoOnion = types.HostnameInfoOnion
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
import { PackageState } from '../../../../../../core/startos/bindings/PackageState'
import { MainStatus } from '../../../../../../core/startos/bindings/MainStatus'
import { ExportedOnionHostname } from '../../../../../../core/startos/bindings/ExportedOnionHostname'
import { ExportedIpHostname } from '../../../../../../core/startos/bindings/ExportedIpHostname'
import { ExportedHostnameInfo } from '../../../../../../core/startos/bindings/ExportedHostnameInfo'
const {
gitHash,
@@ -56,10 +54,11 @@ export class ConfigService {
return window.isSecureContext || this.isTor()
}
isLaunchable(state: PackageState, status: PackageMainStatus): boolean {
return (
state === PackageState.Installed && status === PackageMainStatus.Running
)
isLaunchable(
state: PackageState['state'],
status: MainStatus['status'],
): boolean {
return state === 'installed' && status === 'running'
}
/** ${scheme}://${username}@${host}:${externalPort}${suffix} */
@@ -76,31 +75,28 @@ export class ConfigService {
const url = new URL(`${scheme}://${username}placeholder${suffix}`)
if (host.kind === 'multi') {
const onionHostname = host.hostnames.find(
(h: any) => h.kind === 'onion',
) as HostnameInfoOnion
const onionHostname = host.hostnames.find(h => h.kind === 'onion')
?.hostname as ExportedOnionHostname
if (this.isTor() && onionHostname) {
url.hostname = onionHostname.hostname.value
url.hostname = onionHostname.value
} else {
const ipHostname = host.hostnames.find(
(h: any) => h.kind === 'ip',
) as HostnameInfoIp
const ipHostname = host.hostnames.find(h => h.kind === 'ip')
?.hostname as ExportedIpHostname
if (!ipHostname) return ''
url.hostname = this.hostname
url.port = String(
ipHostname.hostname.sslPort || ipHostname.hostname.port,
)
url.port = String(ipHostname.sslPort || ipHostname.port)
}
} else {
const hostname = host.hostname
throw new Error('unimplemented')
const hostname = {} as ExportedHostnameInfo // host.hostname
if (!hostname) return ''
if (this.isTor() && hostname.kind === 'onion') {
url.hostname = hostname.hostname.value
url.hostname = (hostname.hostname as ExportedOnionHostname).value
} else {
url.hostname = this.hostname
url.port = String(hostname.hostname.sslPort || hostname.hostname.port)

View File

@@ -4,11 +4,8 @@ import { distinctUntilChanged, map, shareReplay } from 'rxjs/operators'
import { PatchDB } from 'patch-db-client'
import {
DataModel,
HealthResult,
InstalledState,
PackageDataEntry,
PackageMainStatus,
PackageState,
} from './patch-db/data-model'
import * as deepEqual from 'fast-deep-equal'
import { isInstalled } from '../util/get-package-data'
@@ -79,7 +76,7 @@ export class DepErrorService {
const dep = pkgs[depId]
// not installed
if (!dep || dep.stateInfo.state !== PackageState.Installed) {
if (!dep || dep.stateInfo.state !== 'installed') {
return {
type: DependencyErrorType.NotInstalled,
}
@@ -107,19 +104,18 @@ export class DepErrorService {
const depStatus = dep.status.main.status
// not running
if (
depStatus !== PackageMainStatus.Running &&
depStatus !== PackageMainStatus.Starting
) {
if (depStatus !== 'running' && depStatus !== 'starting') {
return {
type: DependencyErrorType.NotRunning,
}
}
const currentDep = pkg.currentDependencies[depId]
// health check failure
if (depStatus === PackageMainStatus.Running) {
for (let id of pkg.currentDependencies[depId].healthChecks) {
if (dep.status.main.health[id]?.result !== HealthResult.Success) {
if (depStatus === 'running' && currentDep.kind === 'running') {
for (let id of currentDep.healthChecks) {
if (dep.status.main.health[id]?.result !== 'success') {
return {
type: DependencyErrorType.HealthChecksFailed,
}

View File

@@ -19,7 +19,11 @@ 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,
UIMarketplaceData,
UIStore,
} from 'src/app/services/patch-db/data-model'
import { PatchDB } from 'patch-db-client'
import {
catchError,
@@ -41,7 +45,7 @@ export class MarketplaceService implements AbstractMarketplaceService {
private readonly knownHosts$: Observable<StoreIdentity[]> = this.patch
.watch$('ui', 'marketplace', 'knownHosts')
.pipe(
map(hosts => {
map((hosts: UIMarketplaceData['knownHosts']) => {
const { start9, community } = this.config.marketplace
let arr = [
toStoreIdentity(start9, hosts[start9]),

View File

@@ -1,13 +1,15 @@
import { Url } from '@start9labs/shared'
import { Manifest } from '@start9labs/marketplace'
import { types } from '@start9labs/start-sdk'
import { ActionMetadata } from '@start9labs/start-sdk/cjs/sdk/lib/types'
import { Public } from '../../../../../../../core/startos/bindings/Public'
import { PackageDataEntry as PDE } from '../../../../../../../core/startos/bindings/PackageDataEntry'
import { FullProgress } from '../../../../../../../core/startos/bindings/FullProgress'
import { Manifest } from '../../../../../../../core/startos/bindings/Manifest'
type ServiceInterfaceWithHostInfo = types.ServiceInterfaceWithHostInfo
export interface DataModel {
serverInfo: ServerInfo
packageData: { [id: string]: PackageDataEntry }
export type DataModel = Public & {
ui: UIData
packageData: Record<string, PackageDataEntry>
}
export interface UIData {
@@ -50,197 +52,31 @@ export interface UIStore {
name?: string
}
export interface ServerInfo {
id: string
version: string
lastBackup: string | null
lanAddress: Url
torAddress: Url
ipInfo: IpInfo
lastWifiRegion: string | null
unreadNotificationCount: number
statusInfo: ServerStatusInfo
eosVersionCompat: string
passwordHash: string
hostname: string
pubkey: string
caFingerprint: string
ntpSynced: boolean
platform: string
}
export interface IpInfo {
[iface: string]: {
ipv4: string | null
ipv6: string | null
}
}
export interface ServerStatusInfo {
backupProgress: null | {
[packageId: string]: {
complete: boolean
}
}
updated: boolean
updateProgress: { size: number | null; downloaded: number } | null
restarting: boolean
shuttingDown: boolean
}
export enum ServerStatus {
Running = 'running',
Updated = 'updated',
BackingUp = 'backing-up',
}
export type PackageDataEntry<T extends StateInfo = StateInfo> = {
export type PackageDataEntry<T extends StateInfo = StateInfo> = PDE & {
stateInfo: T
icon: Url
status: Status
actions: Record<string, ActionMetadata>
lastBackup: string | null
currentDependencies: Record<string, CurrentDependencyInfo>
serviceInterfaces: Record<string, ServiceInterfaceWithHostInfo>
marketplaceUrl: string | null
developerKey: string
}
export type StateInfo = InstalledState | InstallingState | UpdatingState
export type InstalledState = {
state: PackageState.Installed | PackageState.Removing
state: 'installed' | 'removing'
manifest: Manifest
installingInfo?: undefined
}
export type InstallingState = {
state: PackageState.Installing | PackageState.Restoring
state: 'installing' | 'restoring'
installingInfo: InstallingInfo
manifest?: undefined
}
export type UpdatingState = {
state: PackageState.Updating
state: 'updating'
installingInfo: InstallingInfo
manifest: Manifest
}
export enum PackageState {
Installing = 'installing',
Installed = 'installed',
Updating = 'updating',
Removing = 'removing',
Restoring = 'restoring',
}
export interface CurrentDependencyInfo {
title: string
icon: string
kind: 'exists' | 'running'
registryUrl: string
versionSpec: string
healthChecks: string[] // array of health check IDs
}
export interface Status {
configured: boolean
main: MainStatus
dependencyConfigErrors: { [id: string]: string | null }
}
export type MainStatus =
| MainStatusStopped
| MainStatusStopping
| MainStatusStarting
| MainStatusRunning
| MainStatusBackingUp
| MainStatusRestarting
export interface MainStatusStopped {
status: PackageMainStatus.Stopped
}
export interface MainStatusStopping {
status: PackageMainStatus.Stopping
timeout: string
}
export interface MainStatusStarting {
status: PackageMainStatus.Starting
restarting: boolean
}
export interface MainStatusRunning {
status: PackageMainStatus.Running
started: string // UTC date string
health: Record<string, HealthCheckResult>
}
export interface MainStatusBackingUp {
status: PackageMainStatus.BackingUp
started: string | null // UTC date string
}
export interface MainStatusRestarting {
status: PackageMainStatus.Restarting
}
export enum PackageMainStatus {
Starting = 'starting',
Running = 'running',
Stopping = 'stopping',
Stopped = 'stopped',
BackingUp = 'backing-up',
Restarting = 'restarting',
}
export type HealthCheckResult = { name: string } & (
| HealthCheckResultStarting
| HealthCheckResultLoading
| HealthCheckResultDisabled
| HealthCheckResultSuccess
| HealthCheckResultFailure
)
export enum HealthResult {
Starting = 'starting',
Loading = 'loading',
Disabled = 'disabled',
Success = 'success',
Failure = 'failure',
}
export interface HealthCheckResultStarting {
result: HealthResult.Starting
}
export interface HealthCheckResultDisabled {
result: HealthResult.Disabled
}
export interface HealthCheckResultSuccess {
result: HealthResult.Success
message: string
}
export interface HealthCheckResultLoading {
result: HealthResult.Loading
message: string
}
export interface HealthCheckResultFailure {
result: HealthResult.Failure
message: string
}
export type InstallingInfo = {
progress: FullProgress
newManifest: Manifest
}
export type FullProgress = {
overall: Progress
phases: { name: string; progress: Progress }[]
}
export type Progress = boolean | { done: number; total: number | null } // false means indeterminate. true means complete

View File

@@ -1,12 +1,7 @@
import { isEmptyObject } from '@start9labs/shared'
import {
MainStatusStarting,
PackageDataEntry,
PackageMainStatus,
PackageState,
Status,
} from 'src/app/services/patch-db/data-model'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
import { PkgDependencyErrors } from './dep-error.service'
import { Status } from '../../../../../../core/startos/bindings/Status'
export interface PackageStatus {
primary: PrimaryStatus
@@ -22,7 +17,7 @@ export function renderPkgStatus(
let dependency: DependencyStatus | null = null
let health: HealthStatus | null = null
if (pkg.stateInfo.state === PackageState.Installed) {
if (pkg.stateInfo.state === 'installed') {
primary = getPrimaryStatus(pkg.status)
dependency = getDependencyStatus(depErrors)
health = getHealthStatus(pkg.status)
@@ -36,7 +31,7 @@ export function renderPkgStatus(
function getPrimaryStatus(status: Status): PrimaryStatus {
if (!status.configured) {
return PrimaryStatus.NeedsConfig
} else if ((status.main as MainStatusStarting).restarting) {
} else if (status.main.status === 'restarting') {
return PrimaryStatus.Restarting
} else {
return status.main.status as any as PrimaryStatus
@@ -50,7 +45,7 @@ function getDependencyStatus(depErrors: PkgDependencyErrors): DependencyStatus {
}
function getHealthStatus(status: Status): HealthStatus | null {
if (status.main.status !== PackageMainStatus.Running || !status.main.health) {
if (status.main.status !== 'running' || !status.main.health) {
return null
}

View File

@@ -4,11 +4,10 @@ import {
InstalledState,
InstallingState,
PackageDataEntry,
PackageState,
UpdatingState,
} from 'src/app/services/patch-db/data-model'
import { firstValueFrom } from 'rxjs'
import { Manifest } from '@start9labs/marketplace'
import { Manifest } from '../../../../../../core/startos/bindings/Manifest'
export async function getPackage(
patch: PatchDB<DataModel>,
@@ -32,29 +31,29 @@ export function getManifest(pkg: PackageDataEntry): Manifest {
export function isInstalled(
pkg: PackageDataEntry,
): pkg is PackageDataEntry<InstalledState> {
return pkg.stateInfo.state === PackageState.Installed
return pkg.stateInfo.state === 'installed'
}
export function isRemoving(
pkg: PackageDataEntry,
): pkg is PackageDataEntry<InstalledState> {
return pkg.stateInfo.state === PackageState.Removing
return pkg.stateInfo.state === 'removing'
}
export function isInstalling(
pkg: PackageDataEntry,
): pkg is PackageDataEntry<InstallingState> {
return pkg.stateInfo.state === PackageState.Installing
return pkg.stateInfo.state === 'installing'
}
export function isRestoring(
pkg: PackageDataEntry,
): pkg is PackageDataEntry<InstallingState> {
return pkg.stateInfo.state === PackageState.Restoring
return pkg.stateInfo.state === 'restoring'
}
export function isUpdating(
pkg: PackageDataEntry,
): pkg is PackageDataEntry<UpdatingState> {
return pkg.stateInfo.state === PackageState.Updating
return pkg.stateInfo.state === 'updating'
}

View File

@@ -1,6 +1,7 @@
import { PatchDB } from 'patch-db-client'
import { DataModel, ServerInfo } from 'src/app/services/patch-db/data-model'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { firstValueFrom } from 'rxjs'
import { ServerInfo } from '../../../../../../core/startos/bindings/ServerInfo'
export async function getServerInfo(
patch: PatchDB<DataModel>,