Browse Source

Task/improve type safety across API services and controllers (#7417)

* fix(api): resolve subscription undefined type errors

* fix(api): resolve session metadata null type errors

* feat(api): add type declaration on promises

* fix(api): resolve price undefined type errors

* fix(api): resolve type errors in benchmark service
pull/7069/merge
Kenrick Tandrian 5 days ago
committed by GitHub
parent
commit
7d338c2c67
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      apps/api/src/app/endpoints/public/public.controller.ts
  2. 4
      apps/api/src/app/import/import.controller.ts
  3. 10
      apps/api/src/app/portfolio/portfolio.controller.ts
  4. 2
      apps/api/src/app/subscription/subscription.service.ts
  5. 17
      apps/api/src/services/benchmark/benchmark.service.ts
  6. 10
      apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts
  7. 8
      apps/api/src/services/data-provider/data-provider.service.ts

6
apps/api/src/app/endpoints/public/public.controller.ts

@ -65,7 +65,7 @@ export class PublicController {
}); });
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) {
hasDetails = user.subscription.type === SubscriptionType.Premium; hasDetails = user?.subscription?.type === SubscriptionType.Premium;
} }
const { filters } = (access.settings ?? {}) as AccessSettings; const { filters } = (access.settings ?? {}) as AccessSettings;
@ -98,7 +98,7 @@ export class PublicController {
sortDirection: 'desc', sortDirection: 'desc',
take: 10, take: 10,
types: [ActivityType.BUY, ActivityType.SELL], types: [ActivityType.BUY, ActivityType.SELL],
userCurrency: user.settings?.settings.baseCurrency ?? DEFAULT_CURRENCY, userCurrency: user?.settings?.settings.baseCurrency ?? DEFAULT_CURRENCY,
userId: user.id, userId: user.id,
withExcludedAccountsAndActivities: false withExcludedAccountsAndActivities: false
}); });
@ -167,7 +167,7 @@ export class PublicController {
this.exchangeRateDataService.toCurrency( this.exchangeRateDataService.toCurrency(
quantity * marketPrice, quantity * marketPrice,
assetProfile.currency, assetProfile.currency,
user.settings?.settings.baseCurrency ?? DEFAULT_CURRENCY user?.settings?.settings.baseCurrency ?? DEFAULT_CURRENCY
) )
); );
}) })

4
apps/api/src/app/import/import.controller.ts

@ -65,7 +65,7 @@ export class ImportController {
if ( if (
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') &&
this.request.user.subscription.type === SubscriptionType.Premium this.request.user.subscription?.type === SubscriptionType.Premium
) { ) {
maxActivitiesToImport = Number.MAX_SAFE_INTEGER; maxActivitiesToImport = Number.MAX_SAFE_INTEGER;
} }
@ -109,7 +109,7 @@ export class ImportController {
if ( if (
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') &&
this.request.user.subscription.type === SubscriptionType.Premium this.request.user.subscription?.type === SubscriptionType.Premium
) { ) {
maxActivitiesToImport = Number.MAX_SAFE_INTEGER; maxActivitiesToImport = Number.MAX_SAFE_INTEGER;
} }

10
apps/api/src/app/portfolio/portfolio.controller.ts

@ -97,7 +97,7 @@ export class PortfolioController {
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) {
hasDetails = hasDetails =
this.request.user.subscription.type === SubscriptionType.Premium; this.request.user.subscription?.type === SubscriptionType.Premium;
} }
const filters = this.apiService.buildFiltersFromQueryParams({ const filters = this.apiService.buildFiltersFromQueryParams({
@ -383,7 +383,7 @@ export class PortfolioController {
if ( if (
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') &&
this.request.user.subscription.type === SubscriptionType.Basic this.request.user.subscription?.type === SubscriptionType.Basic
) { ) {
dividends = dividends.map((item) => { dividends = dividends.map((item) => {
return nullifyValuesInObject(item, ['investment']); return nullifyValuesInObject(item, ['investment']);
@ -511,7 +511,7 @@ export class PortfolioController {
if ( if (
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') &&
this.request.user.subscription.type === SubscriptionType.Basic this.request.user.subscription?.type === SubscriptionType.Basic
) { ) {
investments = investments.map((item) => { investments = investments.map((item) => {
return nullifyValuesInObject(item, ['investment']); return nullifyValuesInObject(item, ['investment']);
@ -623,7 +623,7 @@ export class PortfolioController {
if ( if (
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') &&
this.request.user.subscription.type === SubscriptionType.Basic this.request.user.subscription?.type === SubscriptionType.Basic
) { ) {
performanceInformation.chart = performanceInformation.chart.map( performanceInformation.chart = performanceInformation.chart.map(
(item) => { (item) => {
@ -651,7 +651,7 @@ export class PortfolioController {
if ( if (
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') &&
this.request.user.subscription.type === SubscriptionType.Basic this.request.user.subscription?.type === SubscriptionType.Basic
) { ) {
for (const category of report.xRay.categories) { for (const category of report.xRay.categories) {
category.rules = null; category.rules = null;

2
apps/api/src/app/subscription/subscription.service.ts

@ -149,7 +149,7 @@ export class SubscriptionService {
} }
const subscriptionOffer: SubscriptionOffer = JSON.parse( const subscriptionOffer: SubscriptionOffer = JSON.parse(
session.metadata.subscriptionOffer ?? '{}' session.metadata?.subscriptionOffer ?? '{}'
); );
const durationExtension = subscriptionOffer?.durationExtension; const durationExtension = subscriptionOffer?.durationExtension;

17
apps/api/src/services/benchmark/benchmark.service.ts

@ -18,7 +18,6 @@ import {
BenchmarkProperty, BenchmarkProperty,
BenchmarkResponse BenchmarkResponse
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { BenchmarkTrend } from '@ghostfolio/common/types';
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { SymbolProfile } from '@prisma/client'; import { SymbolProfile } from '@prisma/client';
@ -146,7 +145,7 @@ export class BenchmarkService {
public async addBenchmark({ public async addBenchmark({
dataSource, dataSource,
symbol symbol
}: AssetProfileIdentifier): Promise<Partial<SymbolProfile>> { }: AssetProfileIdentifier): Promise<Partial<SymbolProfile> | undefined> {
const assetProfile = await this.prismaService.symbolProfile.findFirst({ const assetProfile = await this.prismaService.symbolProfile.findFirst({
where: { where: {
dataSource, dataSource,
@ -183,7 +182,7 @@ export class BenchmarkService {
public async deleteBenchmark({ public async deleteBenchmark({
dataSource, dataSource,
symbol symbol
}: AssetProfileIdentifier): Promise<Partial<SymbolProfile>> { }: AssetProfileIdentifier): Promise<Partial<SymbolProfile> | null> {
const assetProfile = await this.prismaService.symbolProfile.findFirst({ const assetProfile = await this.prismaService.symbolProfile.findFirst({
where: { where: {
dataSource, dataSource,
@ -240,12 +239,12 @@ export class BenchmarkService {
enableSharing enableSharing
}); });
const promisesAllTimeHighs: Promise<{ date: Date; marketPrice: number }>[] = const promisesAllTimeHighs: ReturnType<
[]; typeof this.marketDataService.getMax
const promisesBenchmarkTrends: Promise<{ >[] = [];
trend50d: BenchmarkTrend; const promisesBenchmarkTrends: ReturnType<
trend200d: BenchmarkTrend; typeof this.getBenchmarkTrends
}>[] = []; >[] = [];
const quotes = await this.dataProviderService.getQuotes({ const quotes = await this.dataProviderService.getQuotes({
items: benchmarkAssetProfiles.map(({ dataSource, symbol }) => { items: benchmarkAssetProfiles.map(({ dataSource, symbol }) => {

10
apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts

@ -200,13 +200,13 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface {
response.assetClass = assetClass; response.assetClass = assetClass;
response.assetSubClass = assetSubClass; response.assetSubClass = assetSubClass;
response.currency = assetProfile.price.currency; response.currency = assetProfile.price?.currency;
response.dataSource = this.getName(); response.dataSource = this.getName();
response.name = this.formatName({ response.name = this.formatName({
longName: assetProfile.price.longName, longName: assetProfile.price?.longName,
quoteType: assetProfile.price.quoteType, quoteType: assetProfile.price?.quoteType,
shortName: assetProfile.price.shortName, shortName: assetProfile.price?.shortName,
symbol: assetProfile.price.symbol symbol: assetProfile.price?.symbol
}); });
response.symbol = this.convertFromYahooFinanceSymbol( response.symbol = this.convertFromYahooFinanceSymbol(
assetProfile.price.symbol assetProfile.price.symbol

8
apps/api/src/services/data-provider/data-provider.service.ts

@ -99,7 +99,7 @@ export class DataProviderService implements OnModuleInit {
return dataSource; return dataSource;
}); });
const promises = []; const promises: Promise<void>[] = [];
for (const [dataSource, assetProfileIdentifiers] of Object.entries( for (const [dataSource, assetProfileIdentifiers] of Object.entries(
itemsGroupedByDataSource itemsGroupedByDataSource
@ -248,7 +248,7 @@ export class DataProviderService implements OnModuleInit {
if ( if (
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') &&
user.subscription.type === SubscriptionType.Basic user.subscription?.type === SubscriptionType.Basic
) { ) {
const dataProvider = this.getDataProvider(DataSource[dataSource]); const dataProvider = this.getDataProvider(DataSource[dataSource]);
@ -660,7 +660,7 @@ export class DataProviderService implements OnModuleInit {
} else if ( } else if (
dataProvider.getDataProviderInfo().isPremium && dataProvider.getDataProviderInfo().isPremium &&
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') &&
user?.subscription.type === SubscriptionType.Basic user?.subscription?.type === SubscriptionType.Basic
) { ) {
// Skip symbols of Premium data providers for users without subscription // Skip symbols of Premium data providers for users without subscription
return false; return false;
@ -876,7 +876,7 @@ export class DataProviderService implements OnModuleInit {
}) })
.map((lookupItem) => { .map((lookupItem) => {
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) {
if (user.subscription.type === SubscriptionType.Premium) { if (user.subscription?.type === SubscriptionType.Premium) {
lookupItem.dataProviderInfo.isPremium = false; lookupItem.dataProviderInfo.isPremium = false;
} }

Loading…
Cancel
Save