diff --git a/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts b/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts index 35388b36c..86b8ff854 100644 --- a/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts +++ b/frontend/projects/ui/src/app/modals/app-config/app-config.page.ts @@ -145,7 +145,7 @@ export class AppConfigPage { this.saving = true - if (hasCurrentDeps(this.pkg)) { + if (await hasCurrentDeps(this.patch, this.pkgId)) { this.dryConfigure() } else { this.configure() diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-actions/app-actions.page.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-actions/app-actions.page.ts index bd25a1a42..68809574e 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-actions/app-actions.page.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-actions/app-actions.page.ts @@ -120,13 +120,13 @@ export class AppActionsPage { } async tryUninstall(pkg: PackageDataEntry): Promise { - const { title, alerts } = pkg.manifest + const { title, alerts, id } = pkg.manifest let message = alerts.uninstall || `Uninstalling ${title} will permanently delete its data` - if (hasCurrentDeps(pkg)) { + if (await hasCurrentDeps(this.patch, id)) { message = `${message}. Services that depend on ${title} will no longer work properly and may crash` } diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-status/app-show-status.component.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-status/app-show-status.component.ts index 574100678..59812e243 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-status/app-show-status.component.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/components/app-show-status/app-show-status.component.ts @@ -6,6 +6,7 @@ import { PrimaryStatus, } from 'src/app/services/pkg-status-rendering.service' import { + DataModel, InterfaceDef, PackageDataEntry, PackageState, @@ -18,6 +19,7 @@ import { ModalService } from 'src/app/services/modal.service' import { DependencyInfo } from '../../pipes/to-dependencies.pipe' import { hasCurrentDeps } from 'src/app/util/has-deps' import { ConnectionService } from 'src/app/services/connection.service' +import { PatchDB } from 'patch-db-client' @Component({ selector: 'app-show-status', @@ -47,8 +49,13 @@ export class AppShowStatusComponent { private readonly launcherService: UiLauncherService, private readonly modalService: ModalService, private readonly connectionService: ConnectionService, + private readonly patch: PatchDB, ) {} + private get id(): string { + return this.pkg.manifest.id + } + get interfaces(): Record { return this.pkg.manifest.interfaces || {} } @@ -99,10 +106,10 @@ export class AppShowStatusComponent { } async tryStop(): Promise { - const { title, alerts } = this.pkg.manifest + const { title, alerts, id } = this.pkg.manifest let message = alerts.stop || '' - if (hasCurrentDeps(this.pkg)) { + if (await hasCurrentDeps(this.patch, id)) { const depMessage = `Services that depend on ${title} will no longer work properly and may crash` message = message ? `${message}.\n\n${depMessage}` : depMessage } @@ -134,10 +141,12 @@ export class AppShowStatusComponent { } async tryRestart(): Promise { - if (hasCurrentDeps(this.pkg)) { + const { id, title } = this.pkg.manifest + + if (await hasCurrentDeps(this.patch, id)) { const alert = await this.alertCtrl.create({ header: 'Warning', - message: `Services that depend on ${this.pkg.manifest.title} may temporarily experiences issues`, + message: `Services that depend on ${title} may temporarily experiences issues`, buttons: [ { text: 'Cancel', @@ -160,10 +169,6 @@ export class AppShowStatusComponent { } } - private get id(): string { - return this.pkg.manifest.id - } - private async start(): Promise { const loader = await this.loadingCtrl.create({ message: `Starting...`, diff --git a/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-dependencies.pipe.ts b/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-dependencies.pipe.ts index 5fdc4f45e..bd81ef183 100644 --- a/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-dependencies.pipe.ts +++ b/frontend/projects/ui/src/app/pages/apps-routes/app-show/pipes/to-dependencies.pipe.ts @@ -2,8 +2,8 @@ import { Pipe, PipeTransform } from '@angular/core' import { NavigationExtras } from '@angular/router' import { NavController } from '@ionic/angular' import { - DependencyError, DependencyErrorType, + InstalledPackageDataEntry, PackageDataEntry, } from 'src/app/services/patch-db/data-model' import { DependentInfo } from 'src/app/types/dependent-info' @@ -31,24 +31,21 @@ export class ToDependenciesPipe implements PipeTransform { transform(pkg: PackageDataEntry): DependencyInfo[] { if (!pkg.installed) return [] - return Object.keys(pkg.installed?.['current-dependencies']) + return Object.keys(pkg.installed['current-dependencies']) .filter(id => !!pkg.manifest.dependencies[id]) - .map(id => - this.setDepValues(pkg, id, pkg.installed!.status['dependency-errors']), - ) + .map(id => this.setDepValues(pkg.installed!, id)) } private setDepValues( - pkg: PackageDataEntry, + pkg: InstalledPackageDataEntry, id: string, - errors: { [id: string]: DependencyError | null }, ): DependencyInfo { let errorText = '' let actionText = 'View' let action: () => any = () => this.navCtrl.navigateForward(`/services/${id}`) - const error = errors[id] + const error = pkg.status['dependency-errors'][id] if (error) { // health checks failed @@ -84,7 +81,7 @@ export class ToDependenciesPipe implements PipeTransform { errorText = `${errorText}. ${pkg.manifest.title} will not work as expected.` } - const depInfo = pkg.installed?.['dependency-info'][id] + const depInfo = pkg['dependency-info'][id] return { id, @@ -98,7 +95,7 @@ export class ToDependenciesPipe implements PipeTransform { } async fixDep( - pkg: PackageDataEntry, + pkg: InstalledPackageDataEntry, action: 'install' | 'update' | 'configure', id: string, ): Promise { @@ -112,7 +109,7 @@ export class ToDependenciesPipe implements PipeTransform { } private async installDep( - pkg: PackageDataEntry, + pkg: InstalledPackageDataEntry, depId: string, ): Promise { const version = pkg.manifest.dependencies[depId].version @@ -133,7 +130,7 @@ export class ToDependenciesPipe implements PipeTransform { } private async configureDep( - pkg: PackageDataEntry, + pkg: InstalledPackageDataEntry, dependencyId: string, ): Promise { const dependentInfo: DependentInfo = { diff --git a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-controls/marketplace-show-controls.component.ts b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-controls/marketplace-show-controls.component.ts index d9e2d99d8..732427cf2 100644 --- a/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-controls/marketplace-show-controls.component.ts +++ b/frontend/projects/ui/src/app/pages/marketplace-routes/marketplace-show/marketplace-show-controls/marketplace-show-controls.component.ts @@ -84,11 +84,10 @@ export class MarketplaceShowControlsComponent { if (!proceed) return } - if ( - this.emver.compare(this.localVersion, this.pkg.manifest.version) !== - 0 && - hasCurrentDeps(this.localPkg) - ) { + const { id, version } = this.pkg.manifest + + const currentDeps = await hasCurrentDeps(this.patch, id) + if (currentDeps && this.emver.compare(this.localVersion, version) !== 0) { this.dryInstall(url) } else { this.install(url) diff --git a/frontend/projects/ui/src/app/pages/updates/updates.page.ts b/frontend/projects/ui/src/app/pages/updates/updates.page.ts index cfa833e67..b199d31fc 100644 --- a/frontend/projects/ui/src/app/pages/updates/updates.page.ts +++ b/frontend/projects/ui/src/app/pages/updates/updates.page.ts @@ -76,7 +76,7 @@ export class UpdatesPage { delete this.marketplaceService.updateErrors[id] this.marketplaceService.updateQueue[id] = true - if (hasCurrentDeps(local)) { + if (await hasCurrentDeps(this.patch, local.manifest.id)) { this.dryUpdate(manifest, url) } else { this.update(id, version, url) diff --git a/frontend/projects/ui/src/app/pkg-config/config-types.ts b/frontend/projects/ui/src/app/pkg-config/config-types.ts index 08f0b9d26..5f5dfda4c 100644 --- a/frontend/projects/ui/src/app/pkg-config/config-types.ts +++ b/frontend/projects/ui/src/app/pkg-config/config-types.ts @@ -7,7 +7,6 @@ export type ValueType = | 'enum' | 'list' | 'object' - | 'pointer' | 'union' export type ValueSpec = ValueSpecOf @@ -24,8 +23,6 @@ export type ValueSpecOf = T extends 'string' ? ValueSpecList : T extends 'object' ? ValueSpecObject - : T extends 'pointer' - ? ValueSpecPointer : T extends 'union' ? ValueSpecUnion : never @@ -60,16 +57,6 @@ export interface ValueSpecUnion { default: string } -export interface ValueSpecPointer extends WithStandalone { - type: 'pointer' - subtype: 'package' | 'system' - 'package-id': string - target: 'lan-address' | 'tor-address' | 'config' | 'tor-key' - interface: string // will only exist if target = tor-key || tor-address || lan-address - selector?: string // will only exist if target = config - multi?: boolean // will only exist if target = config -} - export interface ValueSpecObject extends WithStandalone { type: 'object' spec: ConfigSpec @@ -81,7 +68,7 @@ export interface WithStandalone { warning?: string } -// no lists of booleans, lists, pointers +// no lists of booleans or lists export type ListValueSpecType = | 'string' | 'number' diff --git a/frontend/projects/ui/src/app/services/api/api.fixures.ts b/frontend/projects/ui/src/app/services/api/api.fixures.ts index d39df0880..0ab90d335 100644 --- a/frontend/projects/ui/src/app/services/api/api.fixures.ts +++ b/frontend/projects/ui/src/app/services/api/api.fixures.ts @@ -309,15 +309,6 @@ export module Mock { }, variants: { internal: { - 'lan-address': { - name: 'LAN Address', - type: 'pointer', - subtype: 'package', - target: 'lan-address', - description: 'the lan address', - interface: 'tor-address', - 'package-id': '12341234', - }, 'friendly-name': { name: 'Friendly Name', type: 'string', @@ -1548,17 +1539,7 @@ export module Mock { warning: 'Careful changing this', }, variants: { - internal: { - 'lan-address': { - name: 'LAN Address', - type: 'pointer', - subtype: 'package', - target: 'lan-address', - 'package-id': 'bitcoind', - description: 'the lan address', - interface: 'asdf', - }, - }, + internal: {}, external: { 'emergency-contact': { name: 'Emergency Contact', @@ -1904,13 +1885,6 @@ export module Mock { 'lan-address': 'bitcoind-p2p-address.local', }, }, - 'system-pointers': [], - 'current-dependents': { - lnd: { - pointers: [], - 'health-checks': [], - }, - }, 'current-dependencies': {}, 'dependency-info': {}, 'marketplace-url': 'https://registry.start9.com/', @@ -1943,16 +1917,8 @@ export module Mock { 'lan-address': 'bitcoinproxy-rpc-address.local', }, }, - 'system-pointers': [], - 'current-dependents': { - lnd: { - pointers: [], - 'health-checks': [], - }, - }, 'current-dependencies': { bitcoind: { - pointers: [], 'health-checks': [], }, }, @@ -2000,15 +1966,11 @@ export module Mock { 'lan-address': 'lnd-grpc-address.local', }, }, - 'system-pointers': [], - 'current-dependents': {}, 'current-dependencies': { bitcoind: { - pointers: [], 'health-checks': [], }, 'btc-rpc-proxy': { - pointers: [], 'health-checks': [], }, }, diff --git a/frontend/projects/ui/src/app/services/api/mock-patch.ts b/frontend/projects/ui/src/app/services/api/mock-patch.ts index 16ce771aa..497fc7344 100644 --- a/frontend/projects/ui/src/app/services/api/mock-patch.ts +++ b/frontend/projects/ui/src/app/services/api/mock-patch.ts @@ -369,15 +369,6 @@ export const mockPatchData: DataModel = { }, variants: { internal: { - 'lan-address': { - name: 'LAN Address', - type: 'pointer', - subtype: 'package', - target: 'lan-address', - 'package-id': 'bitcoind', - description: 'the lan address', - interface: '', - }, 'friendly-name': { name: 'Friendly Name', type: 'string', @@ -454,13 +445,6 @@ export const mockPatchData: DataModel = { 'lan-address': 'bitcoind-p2p-address.local', }, }, - 'system-pointers': [], - 'current-dependents': { - lnd: { - pointers: [], - 'health-checks': [], - }, - }, 'current-dependencies': {}, 'dependency-info': {}, 'marketplace-url': 'https://registry.start9.com/', @@ -654,15 +638,11 @@ export const mockPatchData: DataModel = { 'lan-address': 'lnd-grpc-address.local', }, }, - 'system-pointers': [], - 'current-dependents': {}, 'current-dependencies': { bitcoind: { - pointers: [], 'health-checks': [], }, 'btc-rpc-proxy': { - pointers: [], 'health-checks': [], }, }, diff --git a/frontend/projects/ui/src/app/services/form.service.ts b/frontend/projects/ui/src/app/services/form.service.ts index 66d368b50..ee8f0f136 100644 --- a/frontend/projects/ui/src/app/services/form.service.ts +++ b/frontend/projects/ui/src/app/services/form.service.ts @@ -89,7 +89,6 @@ export class FormService { UntypedFormGroup | UntypedFormArray | UntypedFormControl > = {} Object.entries(config).map(([key, spec]) => { - if (spec.type === 'pointer') return group[key] = this.getFormEntry(spec, current ? current[key] : undefined) }) return this.formBuilder.group(group, { validators }) diff --git a/frontend/projects/ui/src/app/services/patch-db/data-model.ts b/frontend/projects/ui/src/app/services/patch-db/data-model.ts index 43839ae43..2d45dee27 100644 --- a/frontend/projects/ui/src/app/services/patch-db/data-model.ts +++ b/frontend/projects/ui/src/app/services/patch-db/data-model.ts @@ -127,8 +127,6 @@ export interface InstalledPackageDataEntry { status: Status manifest: Manifest 'last-backup': string | null - 'system-pointers': any[] - 'current-dependents': { [id: string]: CurrentDependencyInfo } 'current-dependencies': { [id: string]: CurrentDependencyInfo } 'dependency-info': { [id: string]: { @@ -144,7 +142,6 @@ export interface InstalledPackageDataEntry { } export interface CurrentDependencyInfo { - pointers: any[] 'health-checks': string[] // array of health check IDs } diff --git a/frontend/projects/ui/src/app/util/has-deps.ts b/frontend/projects/ui/src/app/util/has-deps.ts index 94b3fa4cd..bebd0dd42 100644 --- a/frontend/projects/ui/src/app/util/has-deps.ts +++ b/frontend/projects/ui/src/app/util/has-deps.ts @@ -1,7 +1,13 @@ -import { PackageDataEntry } from '../services/patch-db/data-model' +import { PatchDB } from 'patch-db-client' +import { DataModel } from '../services/patch-db/data-model' +import { getAllPackages } from './get-package-data' -export function hasCurrentDeps(pkg: PackageDataEntry): boolean { - return !!Object.keys(pkg.installed?.['current-dependents'] || {}).filter( - depId => depId !== pkg.manifest.id, - ).length +export async function hasCurrentDeps( + patch: PatchDB, + id: string, +): Promise { + const pkgs = await getAllPackages(patch) + return !!Object.keys(pkgs) + .filter(pkgId => pkgId !== id) + .find(pkgId => pkgs[pkgId].installed?.['current-dependencies'][pkgId]) }