From f796ea628edb3ccdcc2ebf0f4ecacdcc4b8bc85b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 1 Dec 2025 20:37:02 +0100 Subject: [PATCH 1/9] Bugfix/improve search by name in FMP service (#6012) * Improve search by name * Update changelog --- CHANGELOG.md | 1 + .../financial-modeling-prep.service.ts | 28 ++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4cf9b41b..4bcea795c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Improved the country weightings in the _Financial Modeling Prep_ service +- Improved the search functionality by name in the _Financial Modeling Prep_ service ## 2.220.0 - 2025-11-29 diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts index 27f462c90..2b4193af5 100644 --- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts +++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts @@ -41,6 +41,7 @@ import { isSameDay, parseISO } from 'date-fns'; +import { uniqBy } from 'lodash'; @Injectable() export class FinancialModelingPrepService implements DataProviderInterface { @@ -549,14 +550,27 @@ export class FinancialModelingPrepService implements DataProviderInterface { apikey: this.apiKey }); - const result = await fetch( - `${this.getUrl({ version: 'stable' })}/search-symbol?${queryParams.toString()}`, - { - signal: AbortSignal.timeout( - this.configurationService.get('REQUEST_TIMEOUT') - ) + const [nameResults, symbolResults] = await Promise.all([ + fetch( + `${this.getUrl({ version: 'stable' })}/search-name?${queryParams.toString()}`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()), + fetch( + `${this.getUrl({ version: 'stable' })}/search-symbol?${queryParams.toString()}`, + { + signal: AbortSignal.timeout(requestTimeout) + } + ).then((res) => res.json()) + ]); + + const result = uniqBy( + [...nameResults, ...symbolResults], + ({ exchange, symbol }) => { + return `${exchange}-${symbol}`; } - ).then((res) => res.json()); + ); items = result .filter(({ exchange, symbol }) => { From d0d1a2ac88738b58f717e7199525621d954a756b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 1 Dec 2025 20:38:50 +0100 Subject: [PATCH 2/9] Task/extend subscription offer key type (#6022) * Extend SubscriptionOfferKey --- apps/api/src/app/subscription/subscription.service.ts | 2 ++ libs/common/src/lib/types/subscription-offer-key.type.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/api/src/app/subscription/subscription.service.ts b/apps/api/src/app/subscription/subscription.service.ts index 0458005c9..0fad8c8ac 100644 --- a/apps/api/src/app/subscription/subscription.service.ts +++ b/apps/api/src/app/subscription/subscription.service.ts @@ -179,6 +179,8 @@ export class SubscriptionService { offerKey = 'renewal-early-bird-2023'; } else if (isBefore(createdAt, parseDate('2024-01-01'))) { offerKey = 'renewal-early-bird-2024'; + } else if (isBefore(createdAt, parseDate('2025-12-01'))) { + offerKey = 'renewal-early-bird-2025'; } const offer = await this.getSubscriptionOffer({ diff --git a/libs/common/src/lib/types/subscription-offer-key.type.ts b/libs/common/src/lib/types/subscription-offer-key.type.ts index f6d898a01..89322a400 100644 --- a/libs/common/src/lib/types/subscription-offer-key.type.ts +++ b/libs/common/src/lib/types/subscription-offer-key.type.ts @@ -2,4 +2,5 @@ export type SubscriptionOfferKey = | 'default' | 'renewal' | 'renewal-early-bird-2023' - | 'renewal-early-bird-2024'; + | 'renewal-early-bird-2024' + | 'renewal-early-bird-2025'; From be947f3710d786f491817a26a467ce8e9f951704 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 1 Dec 2025 20:50:24 +0100 Subject: [PATCH 3/9] Bugfix/user endpoint of admin control panel (#6021) * Fix user endpoint * Update changelog --- CHANGELOG.md | 1 + apps/api/src/app/admin/admin.service.ts | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bcea795c..be205d877 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the country weightings in the _Financial Modeling Prep_ service - Improved the search functionality by name in the _Financial Modeling Prep_ service +- Resolved an issue in the user endpoint where the list was returning empty in the admin control panel’s users section ## 2.220.0 - 2025-11-29 diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts index 0a6df7647..705085a48 100644 --- a/apps/api/src/app/admin/admin.service.ts +++ b/apps/api/src/app/admin/admin.service.ts @@ -532,12 +532,7 @@ export class AdminService { this.countUsersWithAnalytics(), this.getUsersWithAnalytics({ skip, - take, - where: { - NOT: { - analytics: null - } - } + take }) ]); @@ -855,6 +850,20 @@ export class AdminService { } } ]; + + const noAnalyticsCondition: Prisma.UserWhereInput['NOT'] = { + analytics: null + }; + + if (where) { + if (where.NOT) { + where.NOT = { ...where.NOT, ...noAnalyticsCondition }; + } else { + where.NOT = noAnalyticsCondition; + } + } else { + where = { NOT: noAnalyticsCondition }; + } } const usersWithAnalytics = await this.prismaService.user.findMany({ From aaa3f93f2265511bb2be1691eb5c41033727157f Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 1 Dec 2025 20:52:33 +0100 Subject: [PATCH 4/9] Release 2.221.0 (#6024) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be205d877..e2e9a0251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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). -## Unreleased +## 2.221.0 - 2025-12-01 ### Changed diff --git a/package-lock.json b/package-lock.json index fe1b24c0f..a3428c3e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.220.0", + "version": "2.221.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.220.0", + "version": "2.221.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 7fb27c0d9..be31efbe9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.220.0", + "version": "2.221.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From 4d065b5a9284bc97ad2d0ceb4af372571df4e26f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20=C5=81=C4=85giewka?= Date: Tue, 2 Dec 2025 12:05:34 +0100 Subject: [PATCH 5/9] Task/upgrade envalid to version 8.1.1 (#6026) * Upgrade envalid to version 8.1.1 * Update changelog --- CHANGELOG.md | 6 ++++++ package-lock.json | 8 ++++---- package.json | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2e9a0251..5271c3b77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## Unreleased + +#### Changed + +- Upgraded `envalid` from version `8.1.0` to `8.1.1` + ## 2.221.0 - 2025-12-01 ### Changed diff --git a/package-lock.json b/package-lock.json index a3428c3e7..78ce506d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,7 @@ "date-fns": "4.1.0", "dotenv": "17.2.3", "dotenv-expand": "12.0.3", - "envalid": "8.1.0", + "envalid": "8.1.1", "fuse.js": "7.1.0", "google-spreadsheet": "3.2.0", "helmet": "7.0.0", @@ -21332,9 +21332,9 @@ } }, "node_modules/envalid": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/envalid/-/envalid-8.1.0.tgz", - "integrity": "sha512-OT6+qVhKVyCidaGoXflb2iK1tC8pd0OV2Q+v9n33wNhUJ+lus+rJobUj4vJaQBPxPZ0vYrPGuxdrenyCAIJcow==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/envalid/-/envalid-8.1.1.tgz", + "integrity": "sha512-vOUfHxAFFvkBjbVQbBfgnCO9d3GcNfMMTtVfgqSU2rQGMFEVqWy9GBuoSfHnwGu7EqR0/GeukQcL3KjFBaga9w==", "license": "MIT", "dependencies": { "tslib": "2.8.1" diff --git a/package.json b/package.json index be31efbe9..dee96482a 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "date-fns": "4.1.0", "dotenv": "17.2.3", "dotenv-expand": "12.0.3", - "envalid": "8.1.0", + "envalid": "8.1.1", "fuse.js": "7.1.0", "google-spreadsheet": "3.2.0", "helmet": "7.0.0", From 2a7514c5a94445aac3452fa2a754dfaf72743100 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 2 Dec 2025 18:57:39 +0100 Subject: [PATCH 6/9] Bugfix/clean up CHANGELOG.md (#5976) * Clean up --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5271c3b77..52ed65258 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2260,7 +2260,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed an issue in the portfolio summary with the currency conversion of fees -- Fixed an issue in the the search for a holding +- Fixed an issue in the search for a holding - Removed the show condition of the experimental features setting in the user settings ## 2.95.0 - 2024-07-12 From 154dbf37a83711acb414c9baf984c5a7b44437eb Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 3 Dec 2025 20:25:56 +0100 Subject: [PATCH 7/9] Task/remove return type in parseSector() of YahooFinanceService (#6006) * Remove return type --- .../data-enhancer/yahoo-finance/yahoo-finance.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts index ecbc38256..65bcd6c06 100644 --- a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts @@ -317,7 +317,7 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { return { assetClass, assetSubClass }; } - private parseSector(aString: string): string { + private parseSector(aString: string) { let sector = UNKNOWN_KEY; switch (aString) { From a623fbb6cf3fc7f230222b87a9364e2fc03479b4 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 4 Dec 2025 20:28:27 +0100 Subject: [PATCH 8/9] Task/upgrade prettier to version 3.7.4 (#6031) * Upgrade prettier to version 3.7.4 * Update changelog --- CHANGELOG.md | 1 + package-lock.json | 8 ++++---- package.json | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52ed65258..a2e9f9823 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### Changed - Upgraded `envalid` from version `8.1.0` to `8.1.1` +- Upgraded `prettier` from version `3.7.3` to `3.7.4` ## 2.221.0 - 2025-12-01 diff --git a/package-lock.json b/package-lock.json index 78ce506d8..6a3829a1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -140,7 +140,7 @@ "jest-environment-jsdom": "29.7.0", "jest-preset-angular": "14.6.0", "nx": "21.5.1", - "prettier": "3.7.3", + "prettier": "3.7.4", "prettier-plugin-organize-attributes": "1.0.0", "prisma": "6.19.0", "react": "18.2.0", @@ -35749,9 +35749,9 @@ } }, "node_modules/prettier": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.3.tgz", - "integrity": "sha512-QgODejq9K3OzoBbuyobZlUhznP5SKwPqp+6Q6xw6o8gnhr4O85L2U915iM2IDcfF2NPXVaM9zlo9tdwipnYwzg==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "dev": true, "license": "MIT", "bin": { diff --git a/package.json b/package.json index dee96482a..5dae615b8 100644 --- a/package.json +++ b/package.json @@ -184,7 +184,7 @@ "jest-environment-jsdom": "29.7.0", "jest-preset-angular": "14.6.0", "nx": "21.5.1", - "prettier": "3.7.3", + "prettier": "3.7.4", "prettier-plugin-organize-attributes": "1.0.0", "prisma": "6.19.0", "react": "18.2.0", From ccea6481abbf7a795477c95aef277286934be039 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 5 Dec 2025 19:53:27 +0100 Subject: [PATCH 9/9] Task/prettify files 20251204 (#6033) * Prettify files --- .../redact-values-in-response.interceptor.ts | 7 +- ...form-data-source-in-request.interceptor.ts | 6 +- ...orm-data-source-in-response.interceptor.ts | 6 +- .../src/app/pages/blog/blog-page.routes.ts | 102 +++++++++--------- .../pages/resources/resources-page.routes.ts | 6 +- ...tfolio-asset-profile-response.interface.ts | 3 +- .../interfaces/simplewebauthn.interface.ts | 75 ++++++------- .../src/lib/validators/is-currency-code.ts | 4 +- .../lib/assistant/interfaces/interfaces.ts | 6 +- .../entity-logo/entity-logo.component.html | 2 +- 10 files changed, 106 insertions(+), 111 deletions(-) diff --git a/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts b/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts index 5e28e1591..5ecf7c48d 100644 --- a/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts +++ b/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts @@ -16,9 +16,10 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable() -export class RedactValuesInResponseInterceptor - implements NestInterceptor -{ +export class RedactValuesInResponseInterceptor implements NestInterceptor< + T, + any +> { public intercept( context: ExecutionContext, next: CallHandler diff --git a/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor.ts b/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor.ts index 3931f362c..3bd9c05e7 100644 --- a/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor.ts +++ b/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor.ts @@ -11,9 +11,9 @@ import { DataSource } from '@prisma/client'; import { Observable } from 'rxjs'; @Injectable() -export class TransformDataSourceInRequestInterceptor - implements NestInterceptor -{ +export class TransformDataSourceInRequestInterceptor< + T +> implements NestInterceptor { public constructor( private readonly configurationService: ConfigurationService ) {} diff --git a/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts index fea5d6fe6..9af256671 100644 --- a/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts +++ b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts @@ -13,9 +13,9 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable() -export class TransformDataSourceInResponseInterceptor - implements NestInterceptor -{ +export class TransformDataSourceInResponseInterceptor< + T +> implements NestInterceptor { private encodedDataSourceMap: { [dataSource: string]: string; } = {}; diff --git a/apps/client/src/app/pages/blog/blog-page.routes.ts b/apps/client/src/app/pages/blog/blog-page.routes.ts index 36d111c19..90d27bdfb 100644 --- a/apps/client/src/app/pages/blog/blog-page.routes.ts +++ b/apps/client/src/app/pages/blog/blog-page.routes.ts @@ -34,117 +34,117 @@ export const routes: Routes = [ canActivate: [AuthGuard], path: '2022/01/ghostfolio-first-months-in-open-source', loadComponent: () => - import( - './2022/01/first-months-in-open-source/first-months-in-open-source-page.component' - ).then((c) => c.FirstMonthsInOpenSourcePageComponent), + import('./2022/01/first-months-in-open-source/first-months-in-open-source-page.component').then( + (c) => c.FirstMonthsInOpenSourcePageComponent + ), title: 'First months in Open Source' }, { canActivate: [AuthGuard], path: '2022/07/ghostfolio-meets-internet-identity', loadComponent: () => - import( - './2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.component' - ).then((c) => c.GhostfolioMeetsInternetIdentityPageComponent), + import('./2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.component').then( + (c) => c.GhostfolioMeetsInternetIdentityPageComponent + ), title: 'Ghostfolio meets Internet Identity' }, { canActivate: [AuthGuard], path: '2022/07/how-do-i-get-my-finances-in-order', loadComponent: () => - import( - './2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component' - ).then((c) => c.HowDoIGetMyFinancesInOrderPageComponent), + import('./2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component').then( + (c) => c.HowDoIGetMyFinancesInOrderPageComponent + ), title: 'How do I get my finances in order?' }, { canActivate: [AuthGuard], path: '2022/08/500-stars-on-github', loadComponent: () => - import( - './2022/08/500-stars-on-github/500-stars-on-github-page.component' - ).then((c) => c.FiveHundredStarsOnGitHubPageComponent), + import('./2022/08/500-stars-on-github/500-stars-on-github-page.component').then( + (c) => c.FiveHundredStarsOnGitHubPageComponent + ), title: '500 Stars on GitHub' }, { canActivate: [AuthGuard], path: '2022/10/hacktoberfest-2022', loadComponent: () => - import( - './2022/10/hacktoberfest-2022/hacktoberfest-2022-page.component' - ).then((c) => c.Hacktoberfest2022PageComponent), + import('./2022/10/hacktoberfest-2022/hacktoberfest-2022-page.component').then( + (c) => c.Hacktoberfest2022PageComponent + ), title: 'Hacktoberfest 2022' }, { canActivate: [AuthGuard], path: '2022/11/black-friday-2022', loadComponent: () => - import( - './2022/11/black-friday-2022/black-friday-2022-page.component' - ).then((c) => c.BlackFriday2022PageComponent), + import('./2022/11/black-friday-2022/black-friday-2022-page.component').then( + (c) => c.BlackFriday2022PageComponent + ), title: 'Black Friday 2022' }, { canActivate: [AuthGuard], path: '2022/12/the-importance-of-tracking-your-personal-finances', loadComponent: () => - import( - './2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.component' - ).then((c) => c.TheImportanceOfTrackingYourPersonalFinancesPageComponent), + import('./2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.component').then( + (c) => c.TheImportanceOfTrackingYourPersonalFinancesPageComponent + ), title: 'The importance of tracking your personal finances' }, { canActivate: [AuthGuard], path: '2023/01/ghostfolio-auf-sackgeld-vorgestellt', loadComponent: () => - import( - './2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.component' - ).then((c) => c.GhostfolioAufSackgeldVorgestelltPageComponent), + import('./2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.component').then( + (c) => c.GhostfolioAufSackgeldVorgestelltPageComponent + ), title: 'Ghostfolio auf Sackgeld.com vorgestellt' }, { canActivate: [AuthGuard], path: '2023/02/ghostfolio-meets-umbrel', loadComponent: () => - import( - './2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.component' - ).then((c) => c.GhostfolioMeetsUmbrelPageComponent), + import('./2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.component').then( + (c) => c.GhostfolioMeetsUmbrelPageComponent + ), title: 'Ghostfolio meets Umbrel' }, { canActivate: [AuthGuard], path: '2023/03/ghostfolio-reaches-1000-stars-on-github', loadComponent: () => - import( - './2023/03/1000-stars-on-github/1000-stars-on-github-page.component' - ).then((c) => c.ThousandStarsOnGitHubPageComponent), + import('./2023/03/1000-stars-on-github/1000-stars-on-github-page.component').then( + (c) => c.ThousandStarsOnGitHubPageComponent + ), title: 'Ghostfolio reaches 1’000 Stars on GitHub' }, { canActivate: [AuthGuard], path: '2023/05/unlock-your-financial-potential-with-ghostfolio', loadComponent: () => - import( - './2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component' - ).then((c) => c.UnlockYourFinancialPotentialWithGhostfolioPageComponent), + import('./2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component').then( + (c) => c.UnlockYourFinancialPotentialWithGhostfolioPageComponent + ), title: 'Unlock your Financial Potential with Ghostfolio' }, { canActivate: [AuthGuard], path: '2023/07/exploring-the-path-to-fire', loadComponent: () => - import( - './2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component' - ).then((c) => c.ExploringThePathToFirePageComponent), + import('./2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component').then( + (c) => c.ExploringThePathToFirePageComponent + ), title: 'Exploring the Path to FIRE' }, { canActivate: [AuthGuard], path: '2023/08/ghostfolio-joins-oss-friends', loadComponent: () => - import( - './2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component' - ).then((c) => c.GhostfolioJoinsOssFriendsPageComponent), + import('./2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component').then( + (c) => c.GhostfolioJoinsOssFriendsPageComponent + ), title: 'Ghostfolio joins OSS Friends' }, { @@ -160,9 +160,9 @@ export const routes: Routes = [ canActivate: [AuthGuard], path: '2023/09/hacktoberfest-2023', loadComponent: () => - import( - './2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component' - ).then((c) => c.Hacktoberfest2023PageComponent), + import('./2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component').then( + (c) => c.Hacktoberfest2023PageComponent + ), title: 'Hacktoberfest 2023' }, { @@ -178,18 +178,18 @@ export const routes: Routes = [ canActivate: [AuthGuard], path: '2023/11/hacktoberfest-2023-debriefing', loadComponent: () => - import( - './2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component' - ).then((c) => c.Hacktoberfest2023DebriefingPageComponent), + import('./2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component').then( + (c) => c.Hacktoberfest2023DebriefingPageComponent + ), title: 'Hacktoberfest 2023 Debriefing' }, { canActivate: [AuthGuard], path: '2024/09/hacktoberfest-2024', loadComponent: () => - import( - './2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component' - ).then((c) => c.Hacktoberfest2024PageComponent), + import('./2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component').then( + (c) => c.Hacktoberfest2024PageComponent + ), title: 'Hacktoberfest 2024' }, { @@ -205,9 +205,9 @@ export const routes: Routes = [ canActivate: [AuthGuard], path: '2025/09/hacktoberfest-2025', loadComponent: () => - import( - './2025/09/hacktoberfest-2025/hacktoberfest-2025-page.component' - ).then((c) => c.Hacktoberfest2025PageComponent), + import('./2025/09/hacktoberfest-2025/hacktoberfest-2025-page.component').then( + (c) => c.Hacktoberfest2025PageComponent + ), title: 'Hacktoberfest 2025' }, { diff --git a/apps/client/src/app/pages/resources/resources-page.routes.ts b/apps/client/src/app/pages/resources/resources-page.routes.ts index 58cdad4d3..107988238 100644 --- a/apps/client/src/app/pages/resources/resources-page.routes.ts +++ b/apps/client/src/app/pages/resources/resources-page.routes.ts @@ -33,9 +33,9 @@ export const routes: Routes = [ { path: publicRoutes.resources.subRoutes.personalFinanceTools.path, loadChildren: () => - import( - './personal-finance-tools/personal-finance-tools-page.routes' - ).then((m) => m.routes) + import('./personal-finance-tools/personal-finance-tools-page.routes').then( + (m) => m.routes + ) } ], path: '', diff --git a/libs/common/src/lib/interfaces/responses/data-provider-ghostfolio-asset-profile-response.interface.ts b/libs/common/src/lib/interfaces/responses/data-provider-ghostfolio-asset-profile-response.interface.ts index 7fd0314fb..3ea635c6d 100644 --- a/libs/common/src/lib/interfaces/responses/data-provider-ghostfolio-asset-profile-response.interface.ts +++ b/libs/common/src/lib/interfaces/responses/data-provider-ghostfolio-asset-profile-response.interface.ts @@ -1,4 +1,3 @@ import { SymbolProfile } from '@prisma/client'; -export interface DataProviderGhostfolioAssetProfileResponse - extends Partial {} +export interface DataProviderGhostfolioAssetProfileResponse extends Partial {} diff --git a/libs/common/src/lib/interfaces/simplewebauthn.interface.ts b/libs/common/src/lib/interfaces/simplewebauthn.interface.ts index ef0a14ffa..69464b961 100644 --- a/libs/common/src/lib/interfaces/simplewebauthn.interface.ts +++ b/libs/common/src/lib/interfaces/simplewebauthn.interface.ts @@ -3,8 +3,7 @@ export interface AuthenticatorAssertionResponse extends AuthenticatorResponse { readonly signature: ArrayBuffer; readonly userHandle: ArrayBuffer | null; } -export interface AuthenticatorAttestationResponse - extends AuthenticatorResponse { +export interface AuthenticatorAttestationResponse extends AuthenticatorResponse { readonly attestationObject: ArrayBuffer; } export interface AuthenticationExtensionsClientInputs { @@ -57,8 +56,7 @@ export interface PublicKeyCredentialRequestOptions { timeout?: number; userVerification?: UserVerificationRequirement; } -export interface PublicKeyCredentialUserEntity - extends PublicKeyCredentialEntity { +export interface PublicKeyCredentialUserEntity extends PublicKeyCredentialEntity { displayName: string; id: BufferSource; } @@ -99,11 +97,10 @@ export declare type BufferSource = ArrayBufferView | ArrayBuffer; export declare type PublicKeyCredentialType = 'public-key'; export declare type UvmEntry = number[]; -export interface PublicKeyCredentialCreationOptionsJSON - extends Omit< - PublicKeyCredentialCreationOptions, - 'challenge' | 'user' | 'excludeCredentials' - > { +export interface PublicKeyCredentialCreationOptionsJSON extends Omit< + PublicKeyCredentialCreationOptions, + 'challenge' | 'user' | 'excludeCredentials' +> { user: PublicKeyCredentialUserEntityJSON; challenge: Base64URLString; excludeCredentials: PublicKeyCredentialDescriptorJSON[]; @@ -113,21 +110,24 @@ export interface PublicKeyCredentialCreationOptionsJSON * A variant of PublicKeyCredentialRequestOptions suitable for JSON transmission to the browser to * (eventually) get passed into navigator.credentials.get(...) in the browser. */ -export interface PublicKeyCredentialRequestOptionsJSON - extends Omit< - PublicKeyCredentialRequestOptions, - 'challenge' | 'allowCredentials' - > { +export interface PublicKeyCredentialRequestOptionsJSON extends Omit< + PublicKeyCredentialRequestOptions, + 'challenge' | 'allowCredentials' +> { challenge: Base64URLString; allowCredentials?: PublicKeyCredentialDescriptorJSON[]; extensions?: AuthenticationExtensionsClientInputs; } -export interface PublicKeyCredentialDescriptorJSON - extends Omit { +export interface PublicKeyCredentialDescriptorJSON extends Omit< + PublicKeyCredentialDescriptor, + 'id' +> { id: Base64URLString; } -export interface PublicKeyCredentialUserEntityJSON - extends Omit { +export interface PublicKeyCredentialUserEntityJSON extends Omit< + PublicKeyCredentialUserEntity, + 'id' +> { id: string; } /** @@ -140,11 +140,10 @@ export interface AttestationCredential extends PublicKeyCredential { * A slightly-modified AttestationCredential to simplify working with ArrayBuffers that * are Base64URL-encoded in the browser so that they can be sent as JSON to the server. */ -export interface AttestationCredentialJSON - extends Omit< - AttestationCredential, - 'response' | 'rawId' | 'getClientExtensionResults' - > { +export interface AttestationCredentialJSON extends Omit< + AttestationCredential, + 'response' | 'rawId' | 'getClientExtensionResults' +> { rawId: Base64URLString; response: AuthenticatorAttestationResponseJSON; clientExtensionResults: AuthenticationExtensionsClientOutputs; @@ -160,11 +159,10 @@ export interface AssertionCredential extends PublicKeyCredential { * A slightly-modified AssertionCredential to simplify working with ArrayBuffers that * are Base64URL-encoded in the browser so that they can be sent as JSON to the server. */ -export interface AssertionCredentialJSON - extends Omit< - AssertionCredential, - 'response' | 'rawId' | 'getClientExtensionResults' - > { +export interface AssertionCredentialJSON extends Omit< + AssertionCredential, + 'response' | 'rawId' | 'getClientExtensionResults' +> { rawId: Base64URLString; response: AuthenticatorAssertionResponseJSON; clientExtensionResults: AuthenticationExtensionsClientOutputs; @@ -173,11 +171,10 @@ export interface AssertionCredentialJSON * A slightly-modified AuthenticatorAttestationResponse to simplify working with ArrayBuffers that * are Base64URL-encoded in the browser so that they can be sent as JSON to the server. */ -export interface AuthenticatorAttestationResponseJSON - extends Omit< - AuthenticatorAttestationResponseFuture, - 'clientDataJSON' | 'attestationObject' - > { +export interface AuthenticatorAttestationResponseJSON extends Omit< + AuthenticatorAttestationResponseFuture, + 'clientDataJSON' | 'attestationObject' +> { clientDataJSON: Base64URLString; attestationObject: Base64URLString; } @@ -185,11 +182,10 @@ export interface AuthenticatorAttestationResponseJSON * A slightly-modified AuthenticatorAssertionResponse to simplify working with ArrayBuffers that * are Base64URL-encoded in the browser so that they can be sent as JSON to the server. */ -export interface AuthenticatorAssertionResponseJSON - extends Omit< - AuthenticatorAssertionResponse, - 'authenticatorData' | 'clientDataJSON' | 'signature' | 'userHandle' - > { +export interface AuthenticatorAssertionResponseJSON extends Omit< + AuthenticatorAssertionResponse, + 'authenticatorData' | 'clientDataJSON' | 'signature' | 'userHandle' +> { authenticatorData: Base64URLString; clientDataJSON: Base64URLString; signature: Base64URLString; @@ -217,8 +213,7 @@ export declare type Base64URLString = string; * * Properties marked optional are not supported in all browsers. */ -export interface AuthenticatorAttestationResponseFuture - extends AuthenticatorAttestationResponse { +export interface AuthenticatorAttestationResponseFuture extends AuthenticatorAttestationResponse { getTransports?: () => AuthenticatorTransport[]; getAuthenticatorData?: () => ArrayBuffer; getPublicKey?: () => ArrayBuffer; diff --git a/libs/common/src/lib/validators/is-currency-code.ts b/libs/common/src/lib/validators/is-currency-code.ts index 771818b05..76c6f4fe2 100644 --- a/libs/common/src/lib/validators/is-currency-code.ts +++ b/libs/common/src/lib/validators/is-currency-code.ts @@ -21,9 +21,7 @@ export function IsCurrencyCode(validationOptions?: ValidationOptions) { } @ValidatorConstraint({ async: false }) -export class IsExtendedCurrencyConstraint - implements ValidatorConstraintInterface -{ +export class IsExtendedCurrencyConstraint implements ValidatorConstraintInterface { public defaultMessage() { return '$property must be a valid ISO4217 currency code'; } diff --git a/libs/ui/src/lib/assistant/interfaces/interfaces.ts b/libs/ui/src/lib/assistant/interfaces/interfaces.ts index e018e0eb6..c00a2b832 100644 --- a/libs/ui/src/lib/assistant/interfaces/interfaces.ts +++ b/libs/ui/src/lib/assistant/interfaces/interfaces.ts @@ -3,8 +3,10 @@ import { AccountWithValue, DateRange } from '@ghostfolio/common/types'; import { SearchMode } from '../enums/search-mode'; -export interface AccountSearchResultItem - extends Pick { +export interface AccountSearchResultItem extends Pick< + AccountWithValue, + 'id' | 'name' +> { mode: SearchMode.ACCOUNT; routerLink: string[]; } diff --git a/libs/ui/src/lib/entity-logo/entity-logo.component.html b/libs/ui/src/lib/entity-logo/entity-logo.component.html index f0abad285..942ea23e5 100644 --- a/libs/ui/src/lib/entity-logo/entity-logo.component.html +++ b/libs/ui/src/lib/entity-logo/entity-logo.component.html @@ -1,6 +1,6 @@ @if (src) {