Merge pull request #2740 from Start9Labs/update/new-registry

Update/new registry
This commit is contained in:
Matt Hill
2024-09-20 09:52:16 -06:00
committed by GitHub
17 changed files with 85 additions and 137 deletions

View File

@@ -14,7 +14,7 @@
## Artifacts ## Artifacts
The StartOS backend is packed into a single binary `startbox` that is symlinked under The StartOS backend is packed into a single binary `startbox` that is symlinked under
several different names for different behaviour: several different names for different behavior:
- `startd`: This is the main daemon of StartOS - `startd`: This is the main daemon of StartOS
- `start-cli`: This is a CLI tool that will allow you to issue commands to - `start-cli`: This is a CLI tool that will allow you to issue commands to

6
package-lock.json generated
View File

@@ -1,6 +0,0 @@
{
"name": "embassy-os",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}

11
web/package-lock.json generated
View File

@@ -1982,7 +1982,7 @@
}, },
"../sdk/dist": { "../sdk/dist": {
"name": "@start9labs/start-sdk", "name": "@start9labs/start-sdk",
"version": "0.3.6-alpha6", "version": "0.3.6-alpha8",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@iarna/toml": "^2.2.5", "@iarna/toml": "^2.2.5",
@@ -1995,10 +1995,8 @@
"yaml": "^2.2.2" "yaml": "^2.2.2"
}, },
"devDependencies": { "devDependencies": {
"@iarna/toml": "^2.2.5",
"@types/jest": "^29.4.0", "@types/jest": "^29.4.0",
"@types/lodash.merge": "^4.6.2", "@types/lodash.merge": "^4.6.2",
"copyfiles": "^2.4.1",
"jest": "^29.4.3", "jest": "^29.4.3",
"peggy": "^3.0.2", "peggy": "^3.0.2",
"prettier": "^3.2.5", "prettier": "^3.2.5",
@@ -2006,8 +2004,7 @@
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"ts-pegjs": "^4.2.1", "ts-pegjs": "^4.2.1",
"tsx": "^4.7.1", "tsx": "^4.7.1",
"typescript": "^5.0.4", "typescript": "^5.0.4"
"yaml": "^2.2.2"
} }
}, },
"node_modules/@ampproject/remapping": { "node_modules/@ampproject/remapping": {
@@ -4922,6 +4919,7 @@
}, },
"node_modules/@pkgjs/parseargs": { "node_modules/@pkgjs/parseargs": {
"version": "0.11.0", "version": "0.11.0",
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"engines": { "engines": {
@@ -7546,6 +7544,7 @@
}, },
"node_modules/encoding": { "node_modules/encoding": {
"version": "0.1.13", "version": "0.1.13",
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
@@ -7554,6 +7553,7 @@
}, },
"node_modules/encoding/node_modules/iconv-lite": { "node_modules/encoding/node_modules/iconv-lite": {
"version": "0.6.3", "version": "0.6.3",
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
@@ -8152,6 +8152,7 @@
}, },
"node_modules/fsevents": { "node_modules/fsevents": {
"version": "2.3.3", "version": "2.3.3",
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [

View File

@@ -1,13 +1,13 @@
{ {
"name": "@start9labs/marketplace", "name": "@start9labs/marketplace",
"version": "0.3.28", "version": "0.3.32",
"peerDependencies": { "peerDependencies": {
"@angular/common": ">=13.2.0", "@angular/common": ">=13.2.0",
"@angular/core": ">=13.2.0", "@angular/core": ">=13.2.0",
"@start9labs/shared": ">=0.3.2", "@start9labs/shared": ">=0.3.2",
"@taiga-ui/cdk": "4.0.0-rc.6", "@taiga-ui/cdk": ">=4.0.0",
"@taiga-ui/core": "4.0.0-rc.6", "@taiga-ui/core": ">=4.0.0",
"@taiga-ui/layout": "4.0.0-rc.6", "@taiga-ui/layout": ">=4.0.0",
"@tinkoff/ng-dompurify": ">=4.0.0", "@tinkoff/ng-dompurify": ">=4.0.0",
"fuse.js": "^6.4.6" "fuse.js": "^6.4.6"
}, },

View File

@@ -9,7 +9,7 @@
[marketplace]="iconConfig" [marketplace]="iconConfig"
/> />
<h1 [class.tui-skeleton]="!store"> <h1 [class.tui-skeleton]="!store">
{{ store?.info?.name || 'Loading store' }} {{ store?.info?.name || 'Loading store...' }}
</h1> </h1>
<!-- change registry modal --> <!-- change registry modal -->
<ng-content select="[slot=desktop]"></ng-content> <ng-content select="[slot=desktop]"></ng-content>

View File

@@ -1,12 +1,7 @@
import { import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
ChangeDetectionStrategy,
Component,
inject,
Input,
} from '@angular/core'
import { StoreIconComponentModule } from '@start9labs/marketplace'
import { TuiIcon, TuiTitle } from '@taiga-ui/core' import { TuiIcon, TuiTitle } from '@taiga-ui/core'
import { ConfigService } from 'src/app/services/config.service' import { StoreIconComponentModule } from './store-icon/store-icon.component.module'
import { MarketplaceConfig } from '@start9labs/shared'
@Component({ @Component({
standalone: true, standalone: true,
@@ -28,7 +23,8 @@ import { ConfigService } from 'src/app/services/config.service'
imports: [StoreIconComponentModule, TuiIcon, TuiTitle], imports: [StoreIconComponentModule, TuiIcon, TuiTitle],
}) })
export class MarketplaceRegistryComponent { export class MarketplaceRegistryComponent {
readonly marketplace = inject(ConfigService).marketplace @Input()
marketplace!: MarketplaceConfig
@Input() @Input()
registry!: { url: string; selected: boolean; name?: string } registry!: { url: string; selected: boolean; name?: string }

View File

@@ -1,6 +1,6 @@
import { CommonModule } from '@angular/common' import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core' import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { MarketplacePkg } from '@start9labs/marketplace' import { MarketplacePkg } from '../../src/types'
import { Exver, MarkdownPipeModule } from '@start9labs/shared' import { Exver, MarkdownPipeModule } from '@start9labs/shared'
import { TuiButton, TuiDialogContext, TuiLoader } from '@taiga-ui/core' import { TuiButton, TuiDialogContext, TuiLoader } from '@taiga-ui/core'
import { TuiAccordion } from '@taiga-ui/kit' import { TuiAccordion } from '@taiga-ui/kit'

View File

@@ -1,22 +1,12 @@
<div <div class="item-container box-shadow-lg">
class="item-container box-shadow-lg"
*tuiLet="marketplace$ | async as marketplace"
>
<!-- color background --> <!-- color background -->
<div class="background"> <div class="background">
<img <img [src]="determineIcon()" alt="{{ pkg.title }} Icon" />
[src]="determineIcon(marketplace)"
alt="{{ pkg.title }} Icon"
/>
</div> </div>
<!-- darkening overlay --> <!-- darkening overlay -->
<div class="overlay"></div> <div class="overlay"></div>
<!-- icon --> <!-- icon -->
<img <img [src]="determineIcon()" class="icon" alt="{{ pkg.title }} Icon" />
[src]="determineIcon(marketplace)"
class="icon"
alt="{{ pkg.title }} Icon"
/>
<div class="detail"> <div class="detail">
<span class="detail-title" ticker> <span class="detail-title" ticker>
{{ pkg.title }} {{ pkg.title }}

View File

@@ -1,11 +1,5 @@
import { import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
ChangeDetectionStrategy, import { MarketplacePkg } from '../../../types'
Component,
Input,
inject,
} from '@angular/core'
import { MarketplacePkg, StoreIdentity } from '../../../types'
import { AbstractMarketplaceService } from '../../../services/marketplace.service'
@Component({ @Component({
selector: 'marketplace-item', selector: 'marketplace-item',
@@ -17,15 +11,9 @@ export class ItemComponent {
@Input({ required: true }) @Input({ required: true })
pkg!: MarketplacePkg pkg!: MarketplacePkg
private readonly marketplaceService = inject(AbstractMarketplaceService) determineIcon(): string {
readonly marketplace$ = this.marketplaceService.getSelectedHost$() return this.pkg.icon
? this.pkg.icon
determineIcon(marketplace: StoreIdentity | null): string { : 'assets/img/service-icons/fallback.png'
try {
const iconUrl = new URL(this.pkg.icon)
return iconUrl.href
} catch (e) {
return `${marketplace?.url}package/v0/icon/${this.pkg.id}`
}
} }
} }

View File

@@ -2,7 +2,13 @@
<div class="box-container"> <div class="box-container">
<h2 class="additional-detail-title">New in {{ pkg.version }}</h2> <h2 class="additional-detail-title">New in {{ pkg.version }}</h2>
<p [innerHTML]="pkg.releaseNotes | markdown"></p> <p [innerHTML]="pkg.releaseNotes | markdown"></p>
<button tuiButton iconEnd="@tui.chevron-right" (click)="onPast()"> <button
tuiButton
size="s"
appearance="whiteblock"
iconEnd="@tui.chevron-right"
(click)="onPast()"
>
Past Release Notes Past Release Notes
</button> </button>
<h2 class="additional-detail-title" [style.margin-top.rem]="2">About</h2> <h2 class="additional-detail-title" [style.margin-top.rem]="2">About</h2>
@@ -11,6 +17,8 @@
*ngIf="pkg.marketingSite as url" *ngIf="pkg.marketingSite as url"
tuiButton tuiButton
iconEnd="@tui.external-link" iconEnd="@tui.external-link"
size="s"
appearance="glass"
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
[href]="url" [href]="url"

View File

@@ -1,27 +1,17 @@
import { CommonModule, KeyValue } from '@angular/common' import { CommonModule, KeyValue } from '@angular/common'
import { import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
ChangeDetectionStrategy,
Component,
inject,
Input,
} from '@angular/core'
import { RouterModule } from '@angular/router' import { RouterModule } from '@angular/router'
import { ExverPipesModule } from '@start9labs/shared' import { ExverPipesModule } from '@start9labs/shared'
import { T } from '@start9labs/start-sdk' import { T } from '@start9labs/start-sdk'
import { TuiLet } from '@taiga-ui/cdk' import { TuiLet } from '@taiga-ui/cdk'
import { TuiAvatar, TuiLineClamp } from '@taiga-ui/kit' import { TuiAvatar, TuiLineClamp } from '@taiga-ui/kit'
import { AbstractMarketplaceService } from '../../../services/marketplace.service' import { MarketplacePkg } from '../../../types'
import { MarketplacePkg, StoreIdentity } from '../../../types'
@Component({ @Component({
selector: 'marketplace-dep-item', selector: 'marketplace-dep-item',
template: ` template: `
<div class="outer-container" *tuiLet="marketplace$ | async as marketplace"> <div class="outer-container">
<tui-avatar <tui-avatar class="dep-img" size="l" [src]="getImage(dep.key)" />
class="dep-img"
size="l"
[src]="getImage(dep.key, marketplace)"
/>
<div> <div>
<tui-line-clamp [linesLimit]="2" [content]="titleContent" /> <tui-line-clamp [linesLimit]="2" [content]="titleContent" />
<ng-template #titleContent> <ng-template #titleContent>
@@ -117,24 +107,9 @@ export class MarketplaceDepItemComponent {
@Input({ required: true }) @Input({ required: true })
dep!: KeyValue<string, T.DependencyMetadata> dep!: KeyValue<string, T.DependencyMetadata>
private readonly marketplaceService = inject(AbstractMarketplaceService) getImage(key: string) {
readonly marketplace$ = this.marketplaceService.getSelectedHost$()
getImage(key: string, marketplace: StoreIdentity | null) {
const icon = this.pkg.dependencyMetadata[key]?.icon const icon = this.pkg.dependencyMetadata[key]?.icon
const camelToSnakeCase = (str: string) => return icon ? icon : 'assets/img/service-icons/fallback.png'
str.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`)
if (icon) {
try {
const iconUrl = new URL(icon)
return iconUrl.href
} catch (e) {
return `${marketplace?.url}package/v0/icon/${camelToSnakeCase(key)}`
}
} else {
return key.substring(0, 2)
}
} }
getTitle(key: string): string { getTitle(key: string): string {

View File

@@ -1,31 +1,18 @@
import { CommonModule } from '@angular/common' import { CommonModule } from '@angular/common'
import { import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
ChangeDetectionStrategy,
Component,
inject,
Input,
} from '@angular/core'
import { SharedPipesModule, TickerModule } from '@start9labs/shared' import { SharedPipesModule, TickerModule } from '@start9labs/shared'
import { TuiLet } from '@taiga-ui/cdk' import { TuiLet } from '@taiga-ui/cdk'
import { AbstractMarketplaceService } from '../../../services/marketplace.service'
import { MarketplacePkg, StoreIdentity } from '../../../types'
@Component({ @Component({
selector: 'marketplace-package-hero', selector: 'marketplace-package-hero',
template: ` template: `
<div class="outer-container" *tuiLet="marketplace$ | async as marketplace"> <div class="outer-container">
<div class="inner-container box-shadow-lg"> <div class="inner-container box-shadow-lg">
<!-- icon --> <!-- icon -->
<img <img [src]="determineIcon()" alt="{{ pkg.title }} Icon" />
[src]="determineIcon(marketplace) | trustUrl"
alt="{{ pkg.title }} Icon"
/>
<!-- color background --> <!-- color background -->
<div class="color-background"> <div class="color-background">
<img <img [src]="determineIcon()" alt="{{ pkg.title }} background image" />
[src]="determineIcon(marketplace) | trustUrl"
alt="{{ pkg.title }} background image"
/>
</div> </div>
<!-- background darkening overlay --> <!-- background darkening overlay -->
<div class="dark-overlay"></div> <div class="dark-overlay"></div>
@@ -158,7 +145,6 @@ import { MarketplacePkg, StoreIdentity } from '../../../types'
imports: [CommonModule, SharedPipesModule, TickerModule, TuiLet], imports: [CommonModule, SharedPipesModule, TickerModule, TuiLet],
}) })
export class MarketplacePackageHeroComponent { export class MarketplacePackageHeroComponent {
// @TODO Matt this used to be MarketplacePkg
@Input({ required: true }) @Input({ required: true })
pkg!: { pkg!: {
id: string id: string
@@ -168,15 +154,9 @@ export class MarketplacePackageHeroComponent {
icon: string icon: string
} }
private readonly marketplaceService = inject(AbstractMarketplaceService) determineIcon() {
readonly marketplace$ = this.marketplaceService.getSelectedHost$() return this.pkg.icon
? this.pkg.icon
determineIcon(marketplace: StoreIdentity | null) { : 'assets/img/service-icons/fallback.png'
try {
const iconUrl = new URL(this.pkg.icon)
return iconUrl.href
} catch (e) {
return `${marketplace?.url}package/v0/icon/${this.pkg.id}`
}
} }
} }

View File

@@ -27,6 +27,7 @@ export * from './components/store-icon/store-icon.component.module'
export * from './components/store-icon/store-icon.component' export * from './components/store-icon/store-icon.component'
export * from './components/menu/menu.component.module' export * from './components/menu/menu.component.module'
export * from './components/menu/menu.component' export * from './components/menu/menu.component'
export * from './components/registry.component'
export * from './services/marketplace.service' export * from './services/marketplace.service'
export * from './services/category.service' export * from './services/category.service'

View File

@@ -1,15 +1,15 @@
{ {
"name": "@start9labs/shared", "name": "@start9labs/shared",
"version": "0.3.13", "version": "0.3.15",
"peerDependencies": { "peerDependencies": {
"@angular/common": "^17.0.6", "@angular/common": ">=13.2.0",
"@angular/core": "^17.0.6", "@angular/core": ">=13.2.0",
"@angular/router": "^17.0.6", "@angular/router": ">=13.2.0",
"@ng-web-apis/mutation-observer": ">=4.0.0", "@ng-web-apis/mutation-observer": ">=4.0.0",
"@ng-web-apis/resize-observer": ">=4.0.0", "@ng-web-apis/resize-observer": ">=4.0.0",
"@taiga-ui/cdk": "4.0.0-rc.7", "@taiga-ui/cdk": ">=4.0.0",
"@taiga-ui/core": "4.0.0-rc.7", "@taiga-ui/core": ">=4.0.0",
"@taiga-ui/layout": "4.0.0-rc.7", "@taiga-ui/layout": ">=4.0.0",
"@tinkoff/ng-dompurify": ">=4.0.0", "@tinkoff/ng-dompurify": ">=4.0.0",
"ansi-to-html": "^0.7.2" "ansi-to-html": "^0.7.2"
}, },

View File

@@ -31,11 +31,9 @@ import {
BehaviorSubject, BehaviorSubject,
combineLatest, combineLatest,
filter, filter,
firstValueFrom,
map, map,
startWith, startWith,
switchMap, switchMap,
tap,
} from 'rxjs' } from 'rxjs'
@Component({ @Component({
@@ -204,15 +202,14 @@ export class MarketplacePreviewComponent {
readonly flavors$ = this.flavor$.pipe( readonly flavors$ = this.flavor$.pipe(
switchMap(current => switchMap(current =>
this.marketplaceService this.marketplaceService.getSelectedStore$().pipe(
.getSelectedStore$() map(({ packages }) =>
.pipe( packages.filter(
map(({ packages }) => ({ id, flavor }) => id === this.pkgId && flavor !== current,
packages.filter(
({ id, flavor }) => id === this.pkgId && flavor !== current,
),
), ),
), ),
filter(p => p.length > 0),
),
), ),
) )

View File

@@ -11,6 +11,7 @@ import {
import { import {
AbstractMarketplaceService, AbstractMarketplaceService,
StoreIconComponentModule, StoreIconComponentModule,
MarketplaceRegistryComponent,
} from '@start9labs/marketplace' } from '@start9labs/marketplace'
import { TuiDialogService, TuiIcon, TuiTitle, TuiButton } from '@taiga-ui/core' import { TuiDialogService, TuiIcon, TuiTitle, TuiButton } from '@taiga-ui/core'
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus' import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
@@ -21,8 +22,8 @@ import { ApiService } from 'src/app/services/api/embassy-api.service'
import { DataModel, UIStore } from 'src/app/services/patch-db/data-model' import { DataModel, UIStore } from 'src/app/services/patch-db/data-model'
import { MarketplaceService } from 'src/app/services/marketplace.service' import { MarketplaceService } from 'src/app/services/marketplace.service'
import { FormDialogService } from 'src/app/services/form-dialog.service' import { FormDialogService } from 'src/app/services/form-dialog.service'
import { MarketplaceRegistryComponent } from '../components/registry.component'
import { getMarketplaceValueSpec, getPromptOptions } from '../utils/registry' import { getMarketplaceValueSpec, getPromptOptions } from '../utils/registry'
import { ConfigService } from 'src/app/services/config.service'
@Component({ @Component({
standalone: true, standalone: true,
@@ -33,6 +34,7 @@ import { getMarketplaceValueSpec, getPromptOptions } from '../utils/registry'
<button <button
tuiCell tuiCell
[disabled]="registry.selected" [disabled]="registry.selected"
[marketplace]="marketplaceConfig"
[registry]="registry" [registry]="registry"
(click)="connect(registry.url)" (click)="connect(registry.url)"
></button> ></button>
@@ -47,6 +49,7 @@ import { getMarketplaceValueSpec, getPromptOptions } from '../utils/registry'
<button <button
tuiCell tuiCell
[registry]="registry" [registry]="registry"
[marketplace]="marketplaceConfig"
(click)="connect(registry.url)" (click)="connect(registry.url)"
></button> ></button>
<button <button
@@ -95,6 +98,7 @@ export class MarketplaceRegistryModal {
'marketplace', 'marketplace',
'knownHosts', 'knownHosts',
) )
readonly marketplaceConfig = inject(ConfigService).marketplace
readonly stores$ = combineLatest([ readonly stores$ = combineLatest([
this.marketplace.getKnownHosts$(), this.marketplace.getKnownHosts$(),

View File

@@ -541,7 +541,14 @@ export module Mock {
gitHash: 'fakehash', gitHash: 'fakehash',
icon: PROXY_ICON, icon: PROXY_ICON,
sourceVersion: null, sourceVersion: null,
dependencyMetadata: {}, dependencyMetadata: {
bitcoind: {
title: 'Bitcoin Core',
icon: BTC_ICON,
description: 'Used for RPC requests',
optional: false,
},
},
donationUrl: null, donationUrl: null,
alerts: { alerts: {
install: 'test', install: 'test',
@@ -717,7 +724,14 @@ export module Mock {
gitHash: 'fakehash', gitHash: 'fakehash',
icon: PROXY_ICON, icon: PROXY_ICON,
sourceVersion: null, sourceVersion: null,
dependencyMetadata: {}, dependencyMetadata: {
bitcoind: {
title: 'Bitcoin Core',
icon: BTC_ICON,
description: 'Used for RPC requests',
optional: false,
},
},
donationUrl: null, donationUrl: null,
alerts: { alerts: {
install: 'test', install: 'test',