From a0424147d479cb6dbf06e75f4c2d0177b56cf220 Mon Sep 17 00:00:00 2001 From: Kenrick Tandrian <60643640+KenTandrian@users.noreply.github.com> Date: Sun, 15 Mar 2026 14:56:38 +0700 Subject: [PATCH] Task/improve type safety of admin and data services (#6557) * Improve type safety --- libs/ui/src/lib/services/admin.service.ts | 24 +++++++++------- libs/ui/src/lib/services/data.service.ts | 35 +++++++++++++---------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/libs/ui/src/lib/services/admin.service.ts b/libs/ui/src/lib/services/admin.service.ts index 145f134e3..dec2a4dd5 100644 --- a/libs/ui/src/lib/services/admin.service.ts +++ b/libs/ui/src/lib/services/admin.service.ts @@ -21,24 +21,23 @@ import { Filter } from '@ghostfolio/common/interfaces'; import { DateRange } from '@ghostfolio/common/types'; -import { GF_ENVIRONMENT, GfEnvironment } from '@ghostfolio/ui/environment'; +import { GF_ENVIRONMENT } from '@ghostfolio/ui/environment'; import { DataService } from '@ghostfolio/ui/services'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; -import { Inject, Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { SortDirection } from '@angular/material/sort'; import { DataSource, MarketData, Platform } from '@prisma/client'; import { JobStatus } from 'bull'; +import { isNumber } from 'lodash'; @Injectable({ providedIn: 'root' }) export class AdminService { - public constructor( - private dataService: DataService, - @Inject(GF_ENVIRONMENT) private environment: GfEnvironment, - private http: HttpClient - ) {} + private readonly dataService = inject(DataService); + private readonly environment = inject(GF_ENVIRONMENT); + private readonly http = inject(HttpClient); public addAssetProfile({ dataSource, symbol }: AssetProfileIdentifier) { return this.http.post( @@ -132,7 +131,7 @@ export class AdminService { public fetchJobs({ status }: { status?: JobStatus[] }) { let params = new HttpParams(); - if (status?.length > 0) { + if (status && status.length > 0) { params = params.append('status', status.join(',')); } @@ -158,8 +157,13 @@ export class AdminService { }) { let params = new HttpParams(); - params = params.append('skip', skip); - params = params.append('take', take); + if (isNumber(skip)) { + params = params.append('skip', skip); + } + + if (isNumber(take)) { + params = params.append('take', take); + } return this.http.get('/api/v1/admin/user', { params }); } diff --git a/libs/ui/src/lib/services/data.service.ts b/libs/ui/src/lib/services/data.service.ts index 169de067c..f3e3fb81f 100644 --- a/libs/ui/src/lib/services/data.service.ts +++ b/libs/ui/src/lib/services/data.service.ts @@ -65,16 +65,19 @@ import type { import { translate } from '@ghostfolio/ui/i18n'; import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { SortDirection } from '@angular/material/sort'; import { utc } from '@date-fns/utc'; import { + Access as AccessModel, Account, AccountBalance, DataSource, MarketData, Order, - Tag + SymbolProfile, + Tag, + User as UserModel } from '@prisma/client'; import { format, parseISO } from 'date-fns'; import { cloneDeep, groupBy, isNumber } from 'lodash'; @@ -85,12 +88,12 @@ import { map } from 'rxjs/operators'; providedIn: 'root' }) export class DataService { - public constructor(private http: HttpClient) {} + private readonly http = inject(HttpClient); public buildFiltersAsQueryParams({ filters }: { filters?: Filter[] }) { let params = new HttpParams(); - if (filters?.length > 0) { + if (filters && filters.length > 0) { const { ACCOUNT: filtersByAccount, ASSET_CLASS: filtersByAssetClass, @@ -308,45 +311,47 @@ export class DataService { } public deleteAccess(aId: string) { - return this.http.delete(`/api/v1/access/${aId}`); + return this.http.delete(`/api/v1/access/${aId}`); } public deleteAccount(aId: string) { - return this.http.delete(`/api/v1/account/${aId}`); + return this.http.delete(`/api/v1/account/${aId}`); } public deleteAccountBalance(aId: string) { - return this.http.delete(`/api/v1/account-balance/${aId}`); + return this.http.delete(`/api/v1/account-balance/${aId}`); } - public deleteActivities({ filters }) { + public deleteActivities({ filters }: { filters?: Filter[] }) { const params = this.buildFiltersAsQueryParams({ filters }); - return this.http.delete('/api/v1/activities', { params }); + return this.http.delete('/api/v1/activities', { params }); } public deleteActivity(aId: string) { - return this.http.delete(`/api/v1/activities/${aId}`); + return this.http.delete(`/api/v1/activities/${aId}`); } public deleteBenchmark({ dataSource, symbol }: AssetProfileIdentifier) { - return this.http.delete(`/api/v1/benchmarks/${dataSource}/${symbol}`); + return this.http.delete>( + `/api/v1/benchmarks/${dataSource}/${symbol}` + ); } public deleteOwnUser(aData: DeleteOwnUserDto) { - return this.http.delete(`/api/v1/user`, { body: aData }); + return this.http.delete(`/api/v1/user`, { body: aData }); } public deleteTag(aId: string) { - return this.http.delete(`/api/v1/tags/${aId}`); + return this.http.delete(`/api/v1/tags/${aId}`); } public deleteUser(aId: string) { - return this.http.delete(`/api/v1/user/${aId}`); + return this.http.delete(`/api/v1/user/${aId}`); } public deleteWatchlistItem({ dataSource, symbol }: AssetProfileIdentifier) { - return this.http.delete(`/api/v1/watchlist/${dataSource}/${symbol}`); + return this.http.delete(`/api/v1/watchlist/${dataSource}/${symbol}`); } public fetchAccesses() {