diff --git a/.vscode/launch.json b/.vscode/launch.json index 0e38e81e5..fa7c688b8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -26,7 +26,8 @@ "skipFiles": [ "${workspaceFolder}/node_modules/**/*.js", "/**/*.js" - ] + ], + "console": "integratedTerminal" } ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c83f5b78..47fcaf921 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.71.0 - 07.11.2021 + +### Changed + +- Changed the logger from `console.log()` to `Logger.log()` + +### Fixed + +- Fixed an exception in the scraper configuration + ## 1.70.0 - 07.11.2021 ### Changed diff --git a/apps/api/src/app/auth/google.strategy.ts b/apps/api/src/app/auth/google.strategy.ts index 5856acb1c..43def1baf 100644 --- a/apps/api/src/app/auth/google.strategy.ts +++ b/apps/api/src/app/auth/google.strategy.ts @@ -1,5 +1,5 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { Provider } from '@prisma/client'; import { Strategy } from 'passport-google-oauth20'; @@ -41,9 +41,9 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { }; done(null, user); - } catch (err) { - console.error(err); - done(err, false); + } catch (error) { + Logger.error(error); + done(error, false); } } } diff --git a/apps/api/src/app/auth/web-auth.service.ts b/apps/api/src/app/auth/web-auth.service.ts index 8780fabe9..ba60b028b 100644 --- a/apps/api/src/app/auth/web-auth.service.ts +++ b/apps/api/src/app/auth/web-auth.service.ts @@ -6,7 +6,8 @@ import type { RequestWithUser } from '@ghostfolio/common/types'; import { Inject, Injectable, - InternalServerErrorException + InternalServerErrorException, + Logger } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { JwtService } from '@nestjs/jwt'; @@ -94,7 +95,7 @@ export class WebAuthService { }; verification = await verifyRegistrationResponse(opts); } catch (error) { - console.error(error); + Logger.error(error); throw new InternalServerErrorException(error.message); } @@ -192,7 +193,7 @@ export class WebAuthService { }; verification = verifyAuthenticationResponse(opts); } catch (error) { - console.error(error); + Logger.error(error); throw new InternalServerErrorException({ error: error.message }); } diff --git a/apps/api/src/app/import/import.controller.ts b/apps/api/src/app/import/import.controller.ts index a16682957..9ae66247d 100644 --- a/apps/api/src/app/import/import.controller.ts +++ b/apps/api/src/app/import/import.controller.ts @@ -5,6 +5,7 @@ import { Controller, HttpException, Inject, + Logger, Post, UseGuards } from '@nestjs/common'; @@ -39,7 +40,7 @@ export class ImportController { userId: this.request.user.id }); } catch (error) { - console.error(error); + Logger.error(error); throw new HttpException( { diff --git a/apps/api/src/app/info/info.service.ts b/apps/api/src/app/info/info.service.ts index 7aca1b82d..ccf715901 100644 --- a/apps/api/src/app/info/info.service.ts +++ b/apps/api/src/app/info/info.service.ts @@ -6,7 +6,7 @@ import { PrismaService } from '@ghostfolio/api/services/prisma.service'; import { InfoItem } from '@ghostfolio/common/interfaces'; import { Subscription } from '@ghostfolio/common/interfaces/subscription.interface'; import { permissions } from '@ghostfolio/common/permissions'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import * as bent from 'bent'; import { subDays } from 'date-fns'; @@ -109,7 +109,7 @@ export class InfoService { const contributors = await get(); return contributors?.length; } catch (error) { - console.error(error); + Logger.error(error); return undefined; } @@ -130,7 +130,7 @@ export class InfoService { const { stargazers_count } = await get(); return stargazers_count; } catch (error) { - console.error(error); + Logger.error(error); return undefined; } diff --git a/apps/api/src/app/portfolio/portfolio-calculator.ts b/apps/api/src/app/portfolio/portfolio-calculator.ts index 9676edc20..cc2f1c4ed 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator.ts @@ -2,6 +2,7 @@ import { OrderType } from '@ghostfolio/api/models/order-type'; import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces'; import { DATE_FORMAT, parseDate, resetHours } from '@ghostfolio/common/helper'; import { TimelinePosition } from '@ghostfolio/common/interfaces'; +import { Logger } from '@nestjs/common'; import Big from 'big.js'; import { addDays, @@ -236,7 +237,7 @@ export class PortfolioCalculator { if (!marketSymbolMap[nextDate]?.[item.symbol]) { invalidSymbols.push(item.symbol); hasErrors = true; - console.error( + Logger.error( `Missing value for symbol ${item.symbol} at ${nextDate}` ); continue; @@ -269,7 +270,7 @@ export class PortfolioCalculator { if (!initialValue) { invalidSymbols.push(item.symbol); hasErrors = true; - console.error( + Logger.error( `Missing value for symbol ${item.symbol} at ${currentDate}` ); continue; @@ -480,7 +481,7 @@ export class PortfolioCalculator { currentPosition.netPerformancePercentage.mul(currentInitialValue) ); } else if (!currentPosition.quantity.eq(0)) { - console.error( + Logger.error( `Initial value is missing for symbol ${currentPosition.symbol}` ); hasErrors = true; @@ -546,7 +547,7 @@ export class PortfolioCalculator { userCurrency: this.currency }); } catch (error) { - console.error( + Logger.error( `Failed to fetch info for date ${startDate} with exception`, error ); diff --git a/apps/api/src/app/subscription/subscription.controller.ts b/apps/api/src/app/subscription/subscription.controller.ts index 96d5a9ecd..0eb345f63 100644 --- a/apps/api/src/app/subscription/subscription.controller.ts +++ b/apps/api/src/app/subscription/subscription.controller.ts @@ -6,6 +6,7 @@ import { Get, HttpException, Inject, + Logger, Post, Req, Res, @@ -46,7 +47,7 @@ export class SubscriptionController { userId: this.request.user.id }); } catch (error) { - console.error(error); + Logger.error(error); throw new HttpException( getReasonPhrase(StatusCodes.BAD_REQUEST), diff --git a/apps/api/src/app/subscription/subscription.service.ts b/apps/api/src/app/subscription/subscription.service.ts index f735e04f4..2d40cbcc2 100644 --- a/apps/api/src/app/subscription/subscription.service.ts +++ b/apps/api/src/app/subscription/subscription.service.ts @@ -1,7 +1,7 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; import { PrismaService } from '@ghostfolio/api/services/prisma.service'; import { SubscriptionType } from '@ghostfolio/common/types/subscription.type'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { Subscription } from '@prisma/client'; import { addDays, isBefore } from 'date-fns'; import Stripe from 'stripe'; @@ -85,7 +85,7 @@ export class SubscriptionService { description: session.client_reference_id }); } catch (error) { - console.error(error); + Logger.error(error); } } diff --git a/apps/api/src/app/symbol/symbol.service.ts b/apps/api/src/app/symbol/symbol.service.ts index 8940405aa..60a5e481c 100644 --- a/apps/api/src/app/symbol/symbol.service.ts +++ b/apps/api/src/app/symbol/symbol.service.ts @@ -1,7 +1,7 @@ import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces'; import { PrismaService } from '@ghostfolio/api/services/prisma.service'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { DataSource } from '@prisma/client'; import { LookupItem } from './interfaces/lookup-item.interface'; @@ -67,7 +67,7 @@ export class SymbolService { return results; } catch (error) { - console.error(error); + Logger.error(error); throw error; } diff --git a/apps/api/src/services/data-gathering.service.ts b/apps/api/src/services/data-gathering.service.ts index d5f5c7770..6a6d063d9 100644 --- a/apps/api/src/services/data-gathering.service.ts +++ b/apps/api/src/services/data-gathering.service.ts @@ -4,7 +4,7 @@ import { ghostfolioFearAndGreedIndexSymbol } from '@ghostfolio/common/config'; import { DATE_FORMAT, resetHours } from '@ghostfolio/common/helper'; -import { Inject, Injectable } from '@nestjs/common'; +import { Inject, Injectable, Logger } from '@nestjs/common'; import { DataSource } from '@prisma/client'; import { differenceInHours, @@ -41,7 +41,7 @@ export class DataGatheringService { const isDataGatheringNeeded = await this.isDataGatheringNeeded(); if (isDataGatheringNeeded) { - console.log('7d data gathering has been started.'); + Logger.log('7d data gathering has been started.'); console.time('data-gathering-7d'); await this.prismaService.property.create({ @@ -65,7 +65,7 @@ export class DataGatheringService { where: { key: 'LAST_DATA_GATHERING' } }); } catch (error) { - console.error(error); + Logger.error(error); } await this.prismaService.property.delete({ @@ -74,7 +74,7 @@ export class DataGatheringService { } }); - console.log('7d data gathering has been completed.'); + Logger.log('7d data gathering has been completed.'); console.timeEnd('data-gathering-7d'); } } @@ -85,7 +85,7 @@ export class DataGatheringService { }); if (!isDataGatheringLocked) { - console.log('Max data gathering has been started.'); + Logger.log('Max data gathering has been started.'); console.time('data-gathering-max'); await this.prismaService.property.create({ @@ -109,7 +109,7 @@ export class DataGatheringService { where: { key: 'LAST_DATA_GATHERING' } }); } catch (error) { - console.error(error); + Logger.error(error); } await this.prismaService.property.delete({ @@ -118,13 +118,13 @@ export class DataGatheringService { } }); - console.log('Max data gathering has been completed.'); + Logger.log('Max data gathering has been completed.'); console.timeEnd('data-gathering-max'); } } public async gatherProfileData(aDataGatheringItems?: IDataGatheringItem[]) { - console.log('Profile data gathering has been started.'); + Logger.log('Profile data gathering has been started.'); console.time('data-gathering-profile'); let dataGatheringItems = aDataGatheringItems; @@ -152,7 +152,7 @@ export class DataGatheringService { symbol: symbolMapping[dataEnhancer.getName()] ?? symbol }); } catch (error) { - console.error(`Failed to enhance data for symbol ${symbol}`, error); + Logger.error(`Failed to enhance data for symbol ${symbol}`, error); } } @@ -194,11 +194,11 @@ export class DataGatheringService { } }); } catch (error) { - console.error(`${symbol}: ${error?.meta?.cause}`); + Logger.error(`${symbol}: ${error?.meta?.cause}`); } } - console.log('Profile data gathering has been completed.'); + Logger.log('Profile data gathering has been completed.'); console.timeEnd('data-gathering-profile'); } @@ -261,7 +261,7 @@ export class DataGatheringService { } } catch (error) { hasError = true; - console.error(error); + Logger.error(error); } } @@ -291,7 +291,7 @@ export class DataGatheringService { } public async reset() { - console.log('Data gathering has been reset.'); + Logger.log('Data gathering has been reset.'); await this.prismaService.property.deleteMany({ where: { diff --git a/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts b/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts index 3719fbe7c..625bbc627 100644 --- a/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts +++ b/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts @@ -2,7 +2,7 @@ import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.in import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { Granularity } from '@ghostfolio/common/types'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { DataSource } from '@prisma/client'; import { isAfter, isBefore, parse } from 'date-fns'; @@ -78,7 +78,7 @@ export class AlphaVantageService implements DataProviderInterface { return response; } catch (error) { - console.error(error, symbol); + Logger.error(error, symbol); return {}; } diff --git a/apps/api/src/services/data-provider/data-provider.service.ts b/apps/api/src/services/data-provider/data-provider.service.ts index b70b8dd59..8ce146e4b 100644 --- a/apps/api/src/services/data-provider/data-provider.service.ts +++ b/apps/api/src/services/data-provider/data-provider.service.ts @@ -9,7 +9,7 @@ import { import { PrismaService } from '@ghostfolio/api/services/prisma.service'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { Granularity } from '@ghostfolio/common/types'; -import { Inject, Injectable } from '@nestjs/common'; +import { Inject, Injectable, Logger } from '@nestjs/common'; import { DataSource, MarketData } from '@prisma/client'; import { format } from 'date-fns'; import { isEmpty } from 'lodash'; @@ -109,7 +109,7 @@ export class DataProviderService { return r; }, {}); } catch (error) { - console.error(error); + Logger.error(error); } finally { return response; } diff --git a/apps/api/src/services/data-provider/ghostfolio-scraper-api/ghostfolio-scraper-api.service.ts b/apps/api/src/services/data-provider/ghostfolio-scraper-api/ghostfolio-scraper-api.service.ts index 7c30b3dd3..77d406fdb 100644 --- a/apps/api/src/services/data-provider/ghostfolio-scraper-api/ghostfolio-scraper-api.service.ts +++ b/apps/api/src/services/data-provider/ghostfolio-scraper-api/ghostfolio-scraper-api.service.ts @@ -7,7 +7,7 @@ import { isGhostfolioScraperApiSymbol } from '@ghostfolio/common/helper'; import { Granularity } from '@ghostfolio/common/types'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { DataSource } from '@prisma/client'; import * as bent from 'bent'; import * as cheerio from 'cheerio'; @@ -64,7 +64,7 @@ export class GhostfolioScraperApiService implements DataProviderInterface { } }; } catch (error) { - console.error(error); + Logger.error(error); } return {}; @@ -106,7 +106,7 @@ export class GhostfolioScraperApiService implements DataProviderInterface { } }; } catch (error) { - console.error(error); + Logger.error(error); } return {}; diff --git a/apps/api/src/services/data-provider/rakuten-rapid-api/rakuten-rapid-api.service.ts b/apps/api/src/services/data-provider/rakuten-rapid-api/rakuten-rapid-api.service.ts index 0da563de2..b52cc10c4 100644 --- a/apps/api/src/services/data-provider/rakuten-rapid-api/rakuten-rapid-api.service.ts +++ b/apps/api/src/services/data-provider/rakuten-rapid-api/rakuten-rapid-api.service.ts @@ -9,7 +9,7 @@ import { isRakutenRapidApiSymbol } from '@ghostfolio/common/helper'; import { Granularity } from '@ghostfolio/common/types'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { DataSource } from '@prisma/client'; import * as bent from 'bent'; import { format, subMonths, subWeeks, subYears } from 'date-fns'; @@ -61,7 +61,7 @@ export class RakutenRapidApiService implements DataProviderInterface { }; } } catch (error) { - console.error(error); + Logger.error(error); } return {}; @@ -166,7 +166,7 @@ export class RakutenRapidApiService implements DataProviderInterface { const { fgi } = await get(); return fgi; } catch (error) { - console.error(error); + Logger.error(error); return undefined; } diff --git a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts index 925a33df9..2fac41b47 100644 --- a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts @@ -3,7 +3,7 @@ import { CryptocurrencyService } from '@ghostfolio/api/services/cryptocurrency/c import { UNKNOWN_KEY } from '@ghostfolio/common/config'; import { DATE_FORMAT, isCurrency } from '@ghostfolio/common/helper'; import { Granularity } from '@ghostfolio/common/types'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { AssetClass, AssetSubClass, DataSource } from '@prisma/client'; import * as bent from 'bent'; import Big from 'big.js'; @@ -117,7 +117,7 @@ export class YahooFinanceService implements DataProviderInterface { return response; } catch (error) { - console.error(error); + Logger.error(error); return {}; } @@ -169,7 +169,7 @@ export class YahooFinanceService implements DataProviderInterface { return response; } catch (error) { - console.error(error); + Logger.error(error); return {}; } diff --git a/apps/api/src/services/exchange-rate-data.service.ts b/apps/api/src/services/exchange-rate-data.service.ts index f58c71190..26001b911 100644 --- a/apps/api/src/services/exchange-rate-data.service.ts +++ b/apps/api/src/services/exchange-rate-data.service.ts @@ -1,6 +1,6 @@ import { baseCurrency } from '@ghostfolio/common/config'; import { DATE_FORMAT, getYesterday } from '@ghostfolio/common/helper'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { DataSource } from '@prisma/client'; import { format } from 'date-fns'; import { isEmpty, isNumber, uniq } from 'lodash'; @@ -140,7 +140,7 @@ export class ExchangeRateDataService { } // Fallback with error, if currencies are not available - console.error( + Logger.error( `No exchange rate has been found for ${aFromCurrency}${aToCurrency}` ); return aValue; diff --git a/apps/api/src/services/interfaces/symbol-profile.interface.ts b/apps/api/src/services/interfaces/symbol-profile.interface.ts index 5c786729a..e8c00ecd6 100644 --- a/apps/api/src/services/interfaces/symbol-profile.interface.ts +++ b/apps/api/src/services/interfaces/symbol-profile.interface.ts @@ -12,7 +12,7 @@ export interface EnhancedSymbolProfile { dataSource: DataSource; id: string; name: string | null; - scraperConfiguration?: ScraperConfiguration; + scraperConfiguration?: ScraperConfiguration | null; sectors: Sector[]; symbol: string; symbolMapping?: { [key: string]: string }; diff --git a/apps/api/src/services/symbol-profile.service.ts b/apps/api/src/services/symbol-profile.service.ts index 09a59de07..0a95fd6da 100644 --- a/apps/api/src/services/symbol-profile.service.ts +++ b/apps/api/src/services/symbol-profile.service.ts @@ -59,10 +59,14 @@ export class SymbolProfileService { const scraperConfiguration = symbolProfile.scraperConfiguration as Prisma.JsonObject; - return { - selector: scraperConfiguration.selector as string, - url: scraperConfiguration.url as string - }; + if (scraperConfiguration) { + return { + selector: scraperConfiguration.selector as string, + url: scraperConfiguration.url as string + }; + } + + return null; } private getSectors(symbolProfile: SymbolProfile): Sector[] { diff --git a/apps/client/src/main.ts b/apps/client/src/main.ts index 4653539bb..33556621d 100644 --- a/apps/client/src/main.ts +++ b/apps/client/src/main.ts @@ -29,5 +29,5 @@ import { environment } from './environments/environment'; .bootstrapModule(AppModule, { providers: [{ provide: LOCALE_ID, useValue: 'de-CH' }] }) - .catch((err) => console.error(err)); + .catch((error) => console.error(error)); })();