feat: migrate to Angular 14 and RxJS 7 (#1681)

* feat: migrate to Angular 14 and RxJS 7

* chore: update ng-qrcode

* chore: update patch-db

* chore: remove unnecessary generics
This commit is contained in:
Alex Inkin
2022-07-28 06:31:46 +03:00
committed by GitHub
parent 9514b97ca0
commit a5c97d4c24
24 changed files with 4791 additions and 4434 deletions

View File

@@ -426,9 +426,8 @@
} }
} }
}, },
"defaultProject": "ui",
"cli": { "cli": {
"defaultCollection": "@ionic/angular-toolkit" "schematicCollections": ["@ionic/angular-toolkit"]
}, },
"schematics": { "schematics": {
"@ionic/angular-toolkit:component": { "@ionic/angular-toolkit:component": {

File diff suppressed because it is too large Load Diff

View File

@@ -22,15 +22,15 @@
"build-config": "node build-config.js" "build-config": "node build-config.js"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "^13.3.0", "@angular/animations": "^14.1.0",
"@angular/common": "^13.3.0", "@angular/common": "^14.1.0",
"@angular/compiler": "^13.3.0", "@angular/compiler": "^14.1.0",
"@angular/core": "^13.3.0", "@angular/core": "^14.1.0",
"@angular/forms": "^13.3.0", "@angular/forms": "^14.1.0",
"@angular/platform-browser": "^13.3.0", "@angular/platform-browser": "^14.1.0",
"@angular/platform-browser-dynamic": "^13.3.0", "@angular/platform-browser-dynamic": "^14.1.0",
"@angular/router": "^13.3.0", "@angular/router": "^14.1.0",
"@ionic/angular": "^6.0.13", "@ionic/angular": "^6.1.15",
"@ionic/storage-angular": "^3.0.6", "@ionic/storage-angular": "^3.0.6",
"@materia-ui/ngx-monaco-editor": "^6.0.0", "@materia-ui/ngx-monaco-editor": "^6.0.0",
"@start9labs/argon2": "^0.1.0", "@start9labs/argon2": "^0.1.0",
@@ -47,10 +47,10 @@
"marked": "^4.0.0", "marked": "^4.0.0",
"monaco-editor": "^0.33.0", "monaco-editor": "^0.33.0",
"mustache": "^4.2.0", "mustache": "^4.2.0",
"ng-qrcode": "^6.0.0", "ng-qrcode": "^7.0.0",
"patch-db-client": "file: ../../../patch-db/client", "patch-db-client": "file: ../../../patch-db/client",
"pbkdf2": "^3.1.2", "pbkdf2": "^3.1.2",
"rxjs": "^6.6.7", "rxjs": "^7.5.6",
"swiper": "^8.2.4", "swiper": "^8.2.4",
"ts-matches": "^5.1.7", "ts-matches": "^5.1.7",
"tslib": "^2.3.0", "tslib": "^2.3.0",
@@ -58,10 +58,10 @@
"zone.js": "^0.11.5" "zone.js": "^0.11.5"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^13.1.4", "@angular-devkit/build-angular": "^14.1.0",
"@angular/cli": "^13.1.4", "@angular/cli": "^14.1.0",
"@angular/compiler-cli": "^13.3.0", "@angular/compiler-cli": "^14.1.0",
"@angular/language-service": "^13.3.0", "@angular/language-service": "^14.1.0",
"@ionic/cli": "^6.19.0", "@ionic/cli": "^6.19.0",
"@types/aes-js": "^3.1.1", "@types/aes-js": "^3.1.1",
"@types/dompurify": "^2.3.3", "@types/dompurify": "^2.3.3",
@@ -74,7 +74,7 @@
"@types/uuid": "^8.3.1", "@types/uuid": "^8.3.1",
"husky": "^4.3.8", "husky": "^4.3.8",
"lint-staged": "^12.3.7", "lint-staged": "^12.3.7",
"ng-packagr": "^13.3.0", "ng-packagr": "^14.1.0",
"node-html-parser": "^5.3.3", "node-html-parser": "^5.3.3",
"prettier": "^2.6.1", "prettier": "^2.6.1",
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",

View File

@@ -15,7 +15,6 @@ const { useMocks } = require('../../../../config.json') as WorkspaceConfig
@NgModule({ @NgModule({
declarations: [AppComponent], declarations: [AppComponent],
entryComponents: [],
imports: [ imports: [
HttpClientModule, HttpClientModule,
BrowserModule, BrowserModule,

View File

@@ -1,6 +1,7 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { HttpClient } from '@angular/common/http' import { HttpClient } from '@angular/common/http'
import { HttpError, RpcError } from '@start9labs/shared' import { HttpError, RpcError } from '@start9labs/shared'
import { firstValueFrom } from 'rxjs'
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
@@ -16,13 +17,9 @@ export class HttpService {
async httpRequest<T>(body: RPCOptions): Promise<T> { async httpRequest<T>(body: RPCOptions): Promise<T> {
const url = `${window.location.protocol}//${window.location.hostname}:${window.location.port}/rpc/v1` const url = `${window.location.protocol}//${window.location.hostname}:${window.location.port}/rpc/v1`
return this.http return firstValueFrom(this.http.post<T>(url, body)).catch(e => {
.post(url, body) throw new HttpError(e)
.toPromise() })
.then(a => a as T)
.catch(e => {
throw new HttpError(e)
})
} }
} }

View File

@@ -26,7 +26,6 @@ const { useMocks } = require('../../../../config.json') as WorkspaceConfig
@NgModule({ @NgModule({
declarations: [AppComponent], declarations: [AppComponent],
entryComponents: [],
imports: [ imports: [
BrowserModule, BrowserModule,
IonicModule.forRoot({ IonicModule.forRoot({

View File

@@ -1,11 +1,6 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'
HttpClient, import { firstValueFrom, Observable } from 'rxjs'
HttpErrorResponse,
HttpHeaders,
HttpParams,
} from '@angular/common/http'
import { Observable } from 'rxjs'
import * as aesjs from 'aes-js' import * as aesjs from 'aes-js'
import * as pbkdf2 from 'pbkdf2' import * as pbkdf2 from 'pbkdf2'
import { HttpError, RpcError } from '@start9labs/shared' import { HttpError, RpcError } from '@start9labs/shared'
@@ -70,8 +65,7 @@ export class HttpService {
const req = this.http.post(url, options.body, options) const req = this.http.post(url, options.body, options)
return req return firstValueFrom(req)
.toPromise()
.then(res => .then(res =>
AES_CTR.decryptPbkdf2( AES_CTR.decryptPbkdf2(
this.productKey || '', this.productKey || '',
@@ -112,8 +106,7 @@ export class HttpService {
options, options,
) as any ) as any
return req return firstValueFrom(req)
.toPromise()
.then(res => res.body) .then(res => res.body)
.catch(e => { .catch(e => {
throw new HttpError(e) throw new HttpError(e)

View File

@@ -67,8 +67,8 @@ export function partitionArray<T>(
ts: T[], ts: T[],
condition: (t: T) => boolean, condition: (t: T) => boolean,
): [T[], T[]] { ): [T[], T[]] {
const yes = [] as T[] const yes: T[] = []
const no = [] as T[] const no: T[] = []
ts.forEach(t => { ts.forEach(t => {
if (condition(t)) { if (condition(t)) {
yes.push(t) yes.push(t)

View File

@@ -22,7 +22,6 @@ import { PatchDbModule } from './services/patch-db/patch-db.module'
@NgModule({ @NgModule({
declarations: [AppComponent], declarations: [AppComponent],
entryComponents: [],
imports: [ imports: [
HttpClientModule, HttpClientModule,
BrowserAnimationsModule, BrowserAnimationsModule,

View File

@@ -1,6 +1,6 @@
import { Bootstrapper, DBCache } from 'patch-db-client' import { Bootstrapper, DBCache } from 'patch-db-client'
import { APP_INITIALIZER, ErrorHandler, Provider } from '@angular/core' import { APP_INITIALIZER, ErrorHandler, Provider } from '@angular/core'
import { FormBuilder } from '@angular/forms' import { UntypedFormBuilder } from '@angular/forms'
import { Router, RouteReuseStrategy } from '@angular/router' import { Router, RouteReuseStrategy } from '@angular/router'
import { IonicRouteStrategy, IonNav } from '@ionic/angular' import { IonicRouteStrategy, IonNav } from '@ionic/angular'
import { Storage } from '@ionic/storage-angular' import { Storage } from '@ionic/storage-angular'
@@ -20,7 +20,7 @@ const { useMocks } = require('../../../../config.json') as WorkspaceConfig
export const APP_PROVIDERS: Provider[] = [ export const APP_PROVIDERS: Provider[] = [
FilterPackagesPipe, FilterPackagesPipe,
FormBuilder, UntypedFormBuilder,
IonNav, IonNav,
{ {
provide: RouteReuseStrategy, provide: RouteReuseStrategy,

View File

@@ -6,6 +6,7 @@ import { ApiService } from '../../services/api/embassy-api.service'
import { AppWizardComponent, SlideDefinition } from './app-wizard.component' import { AppWizardComponent, SlideDefinition } from './app-wizard.component'
import { ConfigService } from 'src/app/services/config.service' import { ConfigService } from 'src/app/services/config.service'
import { MarketplaceService } from 'src/app/services/marketplace.service' import { MarketplaceService } from 'src/app/services/marketplace.service'
import { firstValueFrom } from 'rxjs'
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class WizardDefs { export class WizardDefs {
@@ -39,12 +40,12 @@ export class WizardDefs {
verb: 'beginning update for', verb: 'beginning update for',
title, title,
Fn: () => Fn: () =>
this.marketplaceService firstValueFrom(
.installPackage({ this.marketplaceService.installPackage({
id, id,
'version-spec': version ? `=${version}` : undefined, 'version-spec': version ? `=${version}` : undefined,
}) }),
.toPromise(), ),
}, },
}, },
] ]
@@ -80,12 +81,12 @@ export class WizardDefs {
verb: 'beginning downgrade for', verb: 'beginning downgrade for',
title, title,
Fn: () => Fn: () =>
this.marketplaceService firstValueFrom(
.installPackage({ this.marketplaceService.installPackage({
id, id,
'version-spec': version ? `=${version}` : undefined, 'version-spec': version ? `=${version}` : undefined,
}) }),
.toPromise(), ),
}, },
}, },
] ]

View File

@@ -1,8 +1,8 @@
import { Component, Input, Output, EventEmitter } from '@angular/core' import { Component, Input, Output, EventEmitter } from '@angular/core'
import { import {
AbstractFormGroupDirective, AbstractFormGroupDirective,
FormArray, UntypedFormArray,
FormGroup, UntypedFormGroup,
} from '@angular/forms' } from '@angular/forms'
import { import {
AlertButton, AlertButton,
@@ -36,7 +36,7 @@ interface Config {
}) })
export class FormObjectComponent { export class FormObjectComponent {
@Input() objectSpec!: ConfigSpec @Input() objectSpec!: ConfigSpec
@Input() formGroup!: FormGroup @Input() formGroup!: UntypedFormGroup
@Input() unionSpec?: ValueSpecUnion @Input() unionSpec?: ValueSpecUnion
@Input() current?: Config @Input() current?: Config
@Input() original?: Config @Input() original?: Config
@@ -153,7 +153,7 @@ export class FormObjectComponent {
} }
addListItem(key: string, markDirty = true, val?: string): void { addListItem(key: string, markDirty = true, val?: string): void {
const arr = this.formGroup.get(key) as FormArray const arr = this.formGroup.get(key) as UntypedFormArray
if (markDirty) arr.markAsDirty() if (markDirty) arr.markAsDirty()
const listSpec = this.objectSpec[key] as ValueSpecList const listSpec = this.objectSpec[key] as ValueSpecList
const newItem = this.formService.getListItem(listSpec, val) const newItem = this.formService.getListItem(listSpec, val)
@@ -330,7 +330,7 @@ export class FormObjectComponent {
private deleteListItem(key: string, index: number, markDirty = true): void { private deleteListItem(key: string, index: number, markDirty = true): void {
if (this.objectListDisplay[key]) if (this.objectListDisplay[key])
this.objectListDisplay[key][index].height = '0px' this.objectListDisplay[key][index].height = '0px'
const arr = this.formGroup.get(key) as FormArray const arr = this.formGroup.get(key) as UntypedFormArray
if (markDirty) arr.markAsDirty() if (markDirty) arr.markAsDirty()
pauseFor(250).then(() => { pauseFor(250).then(() => {
if (this.objectListDisplay[key]) if (this.objectListDisplay[key])

View File

@@ -16,7 +16,7 @@ import { DependentInfo } from 'src/app/types/dependent-info'
import { ConfigSpec } from 'src/app/pkg-config/config-types' import { ConfigSpec } from 'src/app/pkg-config/config-types'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model' import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
import { FormGroup } from '@angular/forms' import { UntypedFormGroup } from '@angular/forms'
import { import {
convertValuesRecursive, convertValuesRecursive,
FormService, FormService,
@@ -40,7 +40,7 @@ export class AppConfigPage {
pkg!: PackageDataEntry pkg!: PackageDataEntry
loadingText!: string loadingText!: string
configSpec!: ConfigSpec configSpec!: ConfigSpec
configForm!: FormGroup configForm!: UntypedFormGroup
original?: object // only if existing config original?: object // only if existing config
diff?: string[] // only if dependent info diff?: string[] // only if dependent info

View File

@@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core' import { Component, Input } from '@angular/core'
import { FormGroup } from '@angular/forms' import { UntypedFormGroup } from '@angular/forms'
import { ModalController } from '@ionic/angular' import { ModalController } from '@ionic/angular'
import { import {
convertValuesRecursive, convertValuesRecursive,
@@ -25,7 +25,7 @@ export class GenericFormPage {
@Input() initialValue: object = {} @Input() initialValue: object = {}
submitBtn!: ActionButton submitBtn!: ActionButton
formGroup!: FormGroup formGroup!: UntypedFormGroup
constructor( constructor(
private readonly modalCtrl: ModalController, private readonly modalCtrl: ModalController,

View File

@@ -14,10 +14,6 @@ export class PackageInfoPipe implements PipeTransform {
transform(pkg: PackageDataEntry): Observable<PkgInfo> { transform(pkg: PackageDataEntry): Observable<PkgInfo> {
return this.patch return this.patch
.watch$('package-data', pkg.manifest.id) .watch$('package-data', pkg.manifest.id)
.pipe( .pipe(filter(Boolean), startWith(pkg), map(getPackageInfo))
filter<PackageDataEntry>(Boolean),
startWith(pkg),
map(getPackageInfo),
)
} }
} }

View File

@@ -21,6 +21,7 @@ import { ApiService } from 'src/app/services/api/embassy-api.service'
import { Breakages } from 'src/app/services/api/api.types' import { Breakages } from 'src/app/services/api/api.types'
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
import { getAllPackages } from 'src/app/util/get-package-data' import { getAllPackages } from 'src/app/util/get-package-data'
import { firstValueFrom } from 'rxjs'
@Component({ @Component({
selector: 'marketplace-show-controls', selector: 'marketplace-show-controls',
@@ -136,12 +137,12 @@ export class MarketplaceShowControlsComponent {
const { id, version } = this.pkg.manifest const { id, version } = this.pkg.manifest
try { try {
await this.marketplaceService await firstValueFrom(
.installPackage({ this.marketplaceService.installPackage({
id, id,
'version-spec': `=${version}`, 'version-spec': `=${version}`,
}) }),
.toPromise() )
} catch (e: any) { } catch (e: any) {
this.errToast.present(e) this.errToast.present(e)
} finally { } finally {

View File

@@ -23,10 +23,7 @@ export class MarketplaceShowPage {
readonly localPkg$ = this.patch readonly localPkg$ = this.patch
.watch$('package-data', this.pkgId) .watch$('package-data', this.pkgId)
.pipe( .pipe(filter(Boolean), shareReplay({ bufferSize: 1, refCount: true }))
filter<PackageDataEntry>(Boolean),
shareReplay({ bufferSize: 1, refCount: true }),
)
readonly pkg$: Observable<MarketplacePkg | null> = this.loadVersion$.pipe( readonly pkg$: Observable<MarketplacePkg | null> = this.loadVersion$.pipe(
switchMap(version => switchMap(version =>

View File

@@ -1,9 +1,9 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { import {
FormArray, UntypedFormArray,
FormBuilder, UntypedFormBuilder,
FormControl, UntypedFormControl,
FormGroup, UntypedFormGroup,
ValidatorFn, ValidatorFn,
Validators, Validators,
} from '@angular/forms' } from '@angular/forms'
@@ -31,12 +31,12 @@ const Mustache = require('mustache')
providedIn: 'root', providedIn: 'root',
}) })
export class FormService { export class FormService {
constructor(private readonly formBuilder: FormBuilder) {} constructor(private readonly formBuilder: UntypedFormBuilder) {}
createForm( createForm(
spec: ConfigSpec, spec: ConfigSpec,
current: { [key: string]: any } = {}, current: { [key: string]: any } = {},
): FormGroup { ): UntypedFormGroup {
return this.getFormGroup(spec, [], current) return this.getFormGroup(spec, [], current)
} }
@@ -44,7 +44,7 @@ export class FormService {
spec: ValueSpecUnion | ListValueSpecUnion, spec: ValueSpecUnion | ListValueSpecUnion,
selection: string, selection: string,
current?: { [key: string]: any } | null, current?: { [key: string]: any } | null,
): FormGroup { ): UntypedFormGroup {
const { variants, tag } = spec const { variants, tag } = spec
const { name, description, warning } = isFullUnion(spec) const { name, description, warning } = isFullUnion(spec)
? spec ? spec
@@ -85,8 +85,11 @@ export class FormService {
config: ConfigSpec, config: ConfigSpec,
validators: ValidatorFn[] = [], validators: ValidatorFn[] = [],
current?: { [key: string]: any } | null, current?: { [key: string]: any } | null,
): FormGroup { ): UntypedFormGroup {
let group: Record<string, FormGroup | FormArray | FormControl> = {} let group: Record<
string,
UntypedFormGroup | UntypedFormArray | UntypedFormControl
> = {}
Object.entries(config).map(([key, spec]) => { Object.entries(config).map(([key, spec]) => {
if (spec.type === 'pointer') return if (spec.type === 'pointer') return
group[key] = this.getFormEntry(spec, current ? current[key] : undefined) group[key] = this.getFormEntry(spec, current ? current[key] : undefined)
@@ -97,7 +100,7 @@ export class FormService {
private getFormEntry( private getFormEntry(
spec: ValueSpec, spec: ValueSpec,
currentValue?: any, currentValue?: any,
): FormGroup | FormArray | FormControl { ): UntypedFormGroup | UntypedFormArray | UntypedFormControl {
let validators: ValidatorFn[] let validators: ValidatorFn[]
let value: any let value: any
switch (spec.type) { switch (spec.type) {
@@ -250,7 +253,7 @@ export function listInRange(stringRange: string): ValidatorFn {
export function listItemIssue(): ValidatorFn { export function listItemIssue(): ValidatorFn {
return parentControl => { return parentControl => {
const { controls } = parentControl as FormArray const { controls } = parentControl as UntypedFormArray
const problemChild = controls.find(c => c.invalid) const problemChild = controls.find(c => c.invalid)
if (problemChild) { if (problemChild) {
return { listItemIssue: { value: 'Invalid entries' } } return { listItemIssue: { value: 'Invalid entries' } }
@@ -512,7 +515,7 @@ function isUnion(spec: any): spec is ListValueSpecUnion {
export function convertValuesRecursive( export function convertValuesRecursive(
configSpec: ConfigSpec, configSpec: ConfigSpec,
group: FormGroup, group: UntypedFormGroup,
) { ) {
Object.entries(configSpec).forEach(([key, valueSpec]) => { Object.entries(configSpec).forEach(([key, valueSpec]) => {
const control = group.get(key) const control = group.get(key)
@@ -524,13 +527,13 @@ export function convertValuesRecursive(
} else if (valueSpec.type === 'string') { } else if (valueSpec.type === 'string') {
if (!control.value) control.setValue(null) if (!control.value) control.setValue(null)
} else if (valueSpec.type === 'object') { } else if (valueSpec.type === 'object') {
convertValuesRecursive(valueSpec.spec, group.get(key) as FormGroup) convertValuesRecursive(valueSpec.spec, group.get(key) as UntypedFormGroup)
} else if (valueSpec.type === 'union') { } else if (valueSpec.type === 'union') {
const formGr = group.get(key) as FormGroup const formGr = group.get(key) as UntypedFormGroup
const spec = valueSpec.variants[formGr.controls[valueSpec.tag.id].value] const spec = valueSpec.variants[formGr.controls[valueSpec.tag.id].value]
convertValuesRecursive(spec, formGr) convertValuesRecursive(spec, formGr)
} else if (valueSpec.type === 'list') { } else if (valueSpec.type === 'list') {
const formArr = group.get(key) as FormArray const formArr = group.get(key) as UntypedFormArray
const { controls } = formArr const { controls } = formArr
if (valueSpec.subtype === 'number') { if (valueSpec.subtype === 'number') {
@@ -544,16 +547,16 @@ export function convertValuesRecursive(
} else if (valueSpec.subtype === 'object') { } else if (valueSpec.subtype === 'object') {
controls.forEach(formGroup => { controls.forEach(formGroup => {
const objectSpec = valueSpec.spec as ListValueSpecObject const objectSpec = valueSpec.spec as ListValueSpecObject
convertValuesRecursive(objectSpec.spec, formGroup as FormGroup) convertValuesRecursive(objectSpec.spec, formGroup as UntypedFormGroup)
}) })
} else if (valueSpec.subtype === 'union') { } else if (valueSpec.subtype === 'union') {
controls.forEach(formGroup => { controls.forEach(formGroup => {
const unionSpec = valueSpec.spec as ListValueSpecUnion const unionSpec = valueSpec.spec as ListValueSpecUnion
const spec = const spec =
unionSpec.variants[ unionSpec.variants[
(formGroup as FormGroup).controls[unionSpec.tag.id].value (formGroup as UntypedFormGroup).controls[unionSpec.tag.id].value
] ]
convertValuesRecursive(spec, formGroup as FormGroup) convertValuesRecursive(spec, formGroup as UntypedFormGroup)
}) })
} }
} }

View File

@@ -1,6 +1,13 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http' import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'
import { from, interval, Observable, race } from 'rxjs' import {
Observable,
from,
interval,
race,
firstValueFrom,
lastValueFrom,
} from 'rxjs'
import { map, take } from 'rxjs/operators' import { map, take } from 'rxjs/operators'
import { ConfigService } from './config.service' import { ConfigService } from './config.service'
import { Revision } from 'patch-db-client' import { Revision } from 'patch-db-client'
@@ -90,8 +97,9 @@ export class HttpService {
break break
} }
return (httpOpts.timeout ? withTimeout(req, httpOpts.timeout) : req) return firstValueFrom(
.toPromise() httpOpts.timeout ? withTimeout(req, httpOpts.timeout) : req,
)
.then(res => res.body) .then(res => res.body)
.catch(e => { .catch(e => {
throw new HttpError(e) throw new HttpError(e)
@@ -183,7 +191,7 @@ function hasParams(
function withTimeout<U>(req: Observable<U>, timeout: number): Observable<U> { function withTimeout<U>(req: Observable<U>, timeout: number): Observable<U> {
return race( return race(
from(req.toPromise()), // this guarantees it only emits on completion, intermediary emissions are suppressed. from(lastValueFrom(req)), // this guarantees it only emits on completion, intermediary emissions are suppressed.
interval(timeout).pipe( interval(timeout).pipe(
take(1), take(1),
map(() => { map(() => {

View File

@@ -1,9 +1,10 @@
import { first } from 'rxjs/operators' import { first } from 'rxjs/operators'
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
import { UIMarketplaceData } from 'src/app/services/patch-db/data-model' import { UIMarketplaceData } from 'src/app/services/patch-db/data-model'
import { firstValueFrom } from 'rxjs'
export function getMarketplace( export function getMarketplace(
patch: PatchDbService, patch: PatchDbService,
): Promise<UIMarketplaceData> { ): Promise<UIMarketplaceData> {
return patch.watch$('ui', 'marketplace').pipe(first()).toPromise() return firstValueFrom(patch.watch$('ui', 'marketplace'))
} }

View File

@@ -1,16 +1,17 @@
import { first } from 'rxjs/operators' import { first } from 'rxjs/operators'
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
import { PackageDataEntry } from 'src/app/services/patch-db/data-model' import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
import { firstValueFrom } from 'rxjs'
export function getPackage( export function getPackage(
patch: PatchDbService, patch: PatchDbService,
id: string, id: string,
): Promise<PackageDataEntry> { ): Promise<PackageDataEntry> {
return patch.watch$('package-data', id).pipe(first()).toPromise() return firstValueFrom(patch.watch$('package-data', id))
} }
export function getAllPackages( export function getAllPackages(
patch: PatchDbService, patch: PatchDbService,
): Promise<Record<string, PackageDataEntry>> { ): Promise<Record<string, PackageDataEntry>> {
return patch.watch$('package-data').pipe(first()).toPromise() return firstValueFrom(patch.watch$('package-data'))
} }

View File

@@ -1,7 +1,8 @@
import { first } from 'rxjs/operators' import { first } from 'rxjs/operators'
import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service'
import { ServerInfo } from 'src/app/services/patch-db/data-model' import { ServerInfo } from 'src/app/services/patch-db/data-model'
import { firstValueFrom } from 'rxjs'
export function getServerInfo(patch: PatchDbService): Promise<ServerInfo> { export function getServerInfo(patch: PatchDbService): Promise<ServerInfo> {
return patch.watch$('server-info').pipe(first()).toPromise() return firstValueFrom(patch.watch$('server-info'))
} }

View File

@@ -16,7 +16,7 @@
"experimentalDecorators": true, "experimentalDecorators": true,
"moduleResolution": "node", "moduleResolution": "node",
"importHelpers": true, "importHelpers": true,
"target": "es2015", "target": "es2020",
"module": "es2020", "module": "es2020",
"lib": ["es2020", "dom"], "lib": ["es2020", "dom"],
"paths": { "paths": {