Browse Source

Merge remote-tracking branch 'origin/main' into feature/enable-strict-null-checks-in-ui

pull/6264/head
Kenrick Tandrian 5 days ago
parent
commit
8f79e0ef3c
  1. 11
      CHANGELOG.md
  2. 12
      apps/client/src/app/pages/about/changelog/changelog-page.component.ts
  3. 12
      apps/client/src/app/pages/about/oss-friends/oss-friends-page.component.ts
  4. 9
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
  5. 8
      apps/client/src/app/pages/resources/resources-page.component.ts
  6. 8
      apps/client/src/locales/messages.zh.xlf
  7. 111
      libs/ui/src/lib/fire-calculator/fire-calculator.component.ts
  8. 227
      package-lock.json
  9. 18
      package.json

11
CHANGELOG.md

@ -5,6 +5,17 @@ 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/), 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). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 2.243.0 - 2026-02-23
### Changed
- Improved the language localization for Chinese (`zh`)
- Upgraded `nestjs` from version `11.1.8` to `11.1.14`
### Fixed
- Fixed an issue when creating activities of type `FEE`, `INTEREST` or `LIABILITY`
## 2.242.0 - 2026-02-22 ## 2.242.0 - 2026-02-22
### Changed ### Changed

12
apps/client/src/app/pages/about/changelog/changelog-page.component.ts

@ -1,7 +1,6 @@
import { Component, OnDestroy } from '@angular/core'; import { Component } from '@angular/core';
import { MarkdownModule } from 'ngx-markdown'; import { MarkdownModule } from 'ngx-markdown';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { Subject } from 'rxjs';
@Component({ @Component({
imports: [MarkdownModule, NgxSkeletonLoaderModule], imports: [MarkdownModule, NgxSkeletonLoaderModule],
@ -9,17 +8,10 @@ import { Subject } from 'rxjs';
styleUrls: ['./changelog-page.scss'], styleUrls: ['./changelog-page.scss'],
templateUrl: './changelog-page.html' templateUrl: './changelog-page.html'
}) })
export class GfChangelogPageComponent implements OnDestroy { export class GfChangelogPageComponent {
public isLoading = true; public isLoading = true;
private unsubscribeSubject = new Subject<void>();
public onLoad() { public onLoad() {
this.isLoading = false; this.isLoading = false;
} }
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
} }

12
apps/client/src/app/pages/about/oss-friends/oss-friends-page.component.ts

@ -1,10 +1,9 @@
import { Component, OnDestroy } from '@angular/core'; import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { IonIcon } from '@ionic/angular/standalone'; import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons'; import { addIcons } from 'ionicons';
import { arrowForwardOutline } from 'ionicons/icons'; import { arrowForwardOutline } from 'ionicons/icons';
import { Subject } from 'rxjs';
const ossFriends = require('../../../../assets/oss-friends.json'); const ossFriends = require('../../../../assets/oss-friends.json');
@ -14,17 +13,10 @@ const ossFriends = require('../../../../assets/oss-friends.json');
styleUrls: ['./oss-friends-page.scss'], styleUrls: ['./oss-friends-page.scss'],
templateUrl: './oss-friends-page.html' templateUrl: './oss-friends-page.html'
}) })
export class GfOpenSourceSoftwareFriendsPageComponent implements OnDestroy { export class GfOpenSourceSoftwareFriendsPageComponent {
public ossFriends = ossFriends.data; public ossFriends = ossFriends.data;
private unsubscribeSubject = new Subject<void>();
public constructor() { public constructor() {
addIcons({ arrowForwardOutline }); addIcons({ arrowForwardOutline });
} }
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
} }

9
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts

@ -501,11 +501,12 @@ export class GfCreateOrUpdateActivityDialogComponent implements OnDestroy {
comment: this.activityForm.get('comment').value || null, comment: this.activityForm.get('comment').value || null,
currency: this.activityForm.get('currency').value, currency: this.activityForm.get('currency').value,
customCurrency: this.activityForm.get('currencyOfUnitPrice').value, customCurrency: this.activityForm.get('currencyOfUnitPrice').value,
dataSource: ['FEE', 'INTEREST', 'LIABILITY', 'VALUABLE'].includes(
this.activityForm.get('type').value
)
? 'MANUAL'
: this.activityForm.get('dataSource').value,
date: this.activityForm.get('date').value, date: this.activityForm.get('date').value,
dataSource:
this.activityForm.get('type').value === 'VALUABLE'
? 'MANUAL'
: this.activityForm.get('dataSource').value,
fee: this.activityForm.get('fee').value, fee: this.activityForm.get('fee').value,
quantity: this.activityForm.get('quantity').value, quantity: this.activityForm.get('quantity').value,
symbol: symbol:

8
apps/client/src/app/pages/resources/resources-page.component.ts

@ -13,7 +13,6 @@ import {
readerOutline readerOutline
} from 'ionicons/icons'; } from 'ionicons/icons';
import { DeviceDetectorService } from 'ngx-device-detector'; import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs';
@Component({ @Component({
host: { class: 'page has-tabs' }, host: { class: 'page has-tabs' },
@ -47,8 +46,6 @@ export class ResourcesPageComponent implements OnInit {
} }
]; ];
private unsubscribeSubject = new Subject<void>();
public constructor(private deviceService: DeviceDetectorService) { public constructor(private deviceService: DeviceDetectorService) {
addIcons({ bookOutline, libraryOutline, newspaperOutline, readerOutline }); addIcons({ bookOutline, libraryOutline, newspaperOutline, readerOutline });
} }
@ -56,9 +53,4 @@ export class ResourcesPageComponent implements OnInit {
public ngOnInit() { public ngOnInit() {
this.deviceType = this.deviceService.getDeviceInfo().deviceType; this.deviceType = this.deviceService.getDeviceInfo().deviceType;
} }
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
} }

8
apps/client/src/locales/messages.zh.xlf

@ -7891,7 +7891,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.feeRatioInitialInvestment" datatype="html"> <trans-unit id="rule.feeRatioInitialInvestment" datatype="html">
<source>Fee Ratio (legacy)</source> <source>Fee Ratio (legacy)</source>
<target state="new">费率</target> <target state="translated">费率(旧版)</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">152</context> <context context-type="linenumber">152</context>
@ -7915,7 +7915,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.feeRatioTotalInvestmentVolume" datatype="html"> <trans-unit id="rule.feeRatioTotalInvestmentVolume" datatype="html">
<source>Fee Ratio</source> <source>Fee Ratio</source>
<target state="new">Fee Ratio</target> <target state="translated">费率</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">161</context> <context context-type="linenumber">161</context>
@ -7923,7 +7923,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.feeRatioTotalInvestmentVolume.false" datatype="html"> <trans-unit id="rule.feeRatioTotalInvestmentVolume.false" datatype="html">
<source>The fees do exceed ${thresholdMax}% of your total investment volume (${feeRatio}%)</source> <source>The fees do exceed ${thresholdMax}% of your total investment volume (${feeRatio}%)</source>
<target state="new">The fees do exceed ${thresholdMax}% of your total investment volume (${feeRatio}%)</target> <target state="translated">费用已超过您总投资金额的 ${thresholdMax}%(${feeRatio}%)</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">163</context> <context context-type="linenumber">163</context>
@ -7931,7 +7931,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.feeRatioTotalInvestmentVolume.true" datatype="html"> <trans-unit id="rule.feeRatioTotalInvestmentVolume.true" datatype="html">
<source>The fees do not exceed ${thresholdMax}% of your total investment volume (${feeRatio}%)</source> <source>The fees do not exceed ${thresholdMax}% of your total investment volume (${feeRatio}%)</source>
<target state="new">The fees do not exceed ${thresholdMax}% of your total investment volume (${feeRatio}%)</target> <target state="translated">费用未超过您总投资金额的 ${thresholdMax}%(${feeRatio}%)</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">167</context> <context context-type="linenumber">167</context>

111
libs/ui/src/lib/fire-calculator/fire-calculator.component.ts

@ -13,13 +13,13 @@ import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ElementRef, ElementRef,
EventEmitter,
Input, Input,
OnChanges, OnChanges,
OnDestroy, OnDestroy,
Output, ViewChild,
ViewChild output
} from '@angular/core'; } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { import {
FormBuilder, FormBuilder,
FormControl, FormControl,
@ -55,9 +55,9 @@ import {
startOfMonth, startOfMonth,
sub sub
} from 'date-fns'; } from 'date-fns';
import { isNumber } from 'lodash'; import { isNil, isNumber } from 'lodash';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { Subject, debounceTime, takeUntil } from 'rxjs'; import { debounceTime } from 'rxjs';
import { FireCalculatorService } from './fire-calculator.service'; import { FireCalculatorService } from './fire-calculator.service';
@ -90,37 +90,31 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy {
@Input() retirementDate: Date; @Input() retirementDate: Date;
@Input() savingsRate = 0; @Input() savingsRate = 0;
@Output() annualInterestRateChanged = new EventEmitter<number>();
@Output() calculationCompleted =
new EventEmitter<FireCalculationCompleteEvent>();
@Output() projectedTotalAmountChanged = new EventEmitter<number>();
@Output() retirementDateChanged = new EventEmitter<Date>();
@Output() savingsRateChanged = new EventEmitter<number>();
@ViewChild('chartCanvas') chartCanvas: ElementRef<HTMLCanvasElement>; @ViewChild('chartCanvas') chartCanvas: ElementRef<HTMLCanvasElement>;
public calculatorForm = this.formBuilder.group({ public calculatorForm = this.formBuilder.group({
// @ts-ignore annualInterestRate: new FormControl<number | null>(null),
annualInterestRate: new FormControl<number>(undefined), paymentPerPeriod: new FormControl<number | null>(null),
// @ts-ignore principalInvestmentAmount: new FormControl<number | null>(null),
paymentPerPeriod: new FormControl<number>(undefined), projectedTotalAmount: new FormControl<number | null>(null),
// @ts-ignore retirementDate: new FormControl<Date | null>(null)
principalInvestmentAmount: new FormControl<number>(undefined),
// @ts-ignore
projectedTotalAmount: new FormControl<number>(undefined),
// @ts-ignore
retirementDate: new FormControl<Date>(undefined)
}); });
public chart: Chart<'bar'>; public chart: Chart<'bar'>;
public isLoading = true; public isLoading = true;
public minDate = addDays(new Date(), 1); public minDate = addDays(new Date(), 1);
public periodsToRetire = 0; public periodsToRetire = 0;
protected readonly annualInterestRateChanged = output<number>();
protected readonly calculationCompleted =
output<FireCalculationCompleteEvent>();
protected readonly projectedTotalAmountChanged = output<number>();
protected readonly retirementDateChanged = output<Date>();
protected readonly savingsRateChanged = output<number>();
private readonly CONTRIBUTION_PERIOD = 12; private readonly CONTRIBUTION_PERIOD = 12;
private readonly DEFAULT_RETIREMENT_DATE = startOfMonth( private readonly DEFAULT_RETIREMENT_DATE = startOfMonth(
addYears(new Date(), 10) addYears(new Date(), 10)
); );
private unsubscribeSubject = new Subject<void>();
public constructor( public constructor(
private changeDetectorRef: ChangeDetectorRef, private changeDetectorRef: ChangeDetectorRef,
@ -136,46 +130,56 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy {
); );
this.calculatorForm.valueChanges this.calculatorForm.valueChanges
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntilDestroyed())
.subscribe(() => { .subscribe(() => {
this.initialize(); this.initialize();
}); });
this.calculatorForm.valueChanges this.calculatorForm.valueChanges
.pipe(debounceTime(500), takeUntil(this.unsubscribeSubject)) .pipe(debounceTime(500), takeUntilDestroyed())
.subscribe(() => { .subscribe(() => {
const { projectedTotalAmount, retirementDate } = const { projectedTotalAmount, retirementDate } =
this.calculatorForm.getRawValue(); this.calculatorForm.getRawValue();
this.calculationCompleted.emit({ if (projectedTotalAmount !== null && retirementDate !== null) {
projectedTotalAmount, this.calculationCompleted.emit({
retirementDate projectedTotalAmount,
}); retirementDate
});
}
}); });
this.calculatorForm this.calculatorForm
.get('annualInterestRate') .get('annualInterestRate')
?.valueChanges.pipe(debounceTime(500), takeUntil(this.unsubscribeSubject)) ?.valueChanges.pipe(debounceTime(500), takeUntilDestroyed())
.subscribe((annualInterestRate) => { .subscribe((annualInterestRate) => {
this.annualInterestRateChanged.emit(annualInterestRate); if (annualInterestRate !== null) {
this.annualInterestRateChanged.emit(annualInterestRate);
}
}); });
this.calculatorForm this.calculatorForm
.get('paymentPerPeriod') .get('paymentPerPeriod')
?.valueChanges.pipe(debounceTime(500), takeUntil(this.unsubscribeSubject)) ?.valueChanges.pipe(debounceTime(500), takeUntilDestroyed())
.subscribe((savingsRate) => { .subscribe((savingsRate) => {
this.savingsRateChanged.emit(savingsRate); if (savingsRate !== null) {
this.savingsRateChanged.emit(savingsRate);
}
}); });
this.calculatorForm this.calculatorForm
.get('projectedTotalAmount') .get('projectedTotalAmount')
?.valueChanges.pipe(debounceTime(500), takeUntil(this.unsubscribeSubject)) ?.valueChanges.pipe(debounceTime(500), takeUntilDestroyed())
.subscribe((projectedTotalAmount) => { .subscribe((projectedTotalAmount) => {
this.projectedTotalAmountChanged.emit(projectedTotalAmount); if (projectedTotalAmount !== null) {
this.projectedTotalAmountChanged.emit(projectedTotalAmount);
}
}); });
this.calculatorForm this.calculatorForm
.get('retirementDate') .get('retirementDate')
?.valueChanges.pipe(debounceTime(500), takeUntil(this.unsubscribeSubject)) ?.valueChanges.pipe(debounceTime(500), takeUntilDestroyed())
.subscribe((retirementDate) => { .subscribe((retirementDate) => {
this.retirementDateChanged.emit(retirementDate); if (retirementDate !== null) {
this.retirementDateChanged.emit(retirementDate);
}
}); });
} }
@ -248,7 +252,9 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy {
normalizedMonthAndYear: Date, normalizedMonthAndYear: Date,
datepicker: MatDatepicker<Date> datepicker: MatDatepicker<Date>
) { ) {
const retirementDate = this.calculatorForm.get('retirementDate')!.value; const retirementDate =
this.calculatorForm.get('retirementDate')?.value ??
this.DEFAULT_RETIREMENT_DATE;
const newRetirementDate = setMonth( const newRetirementDate = setMonth(
setYear(retirementDate, normalizedMonthAndYear.getFullYear()), setYear(retirementDate, normalizedMonthAndYear.getFullYear()),
normalizedMonthAndYear.getMonth() normalizedMonthAndYear.getMonth()
@ -259,9 +265,6 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy {
public ngOnDestroy() { public ngOnDestroy() {
this.chart?.destroy(); this.chart?.destroy();
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
} }
private initialize() { private initialize() {
@ -295,8 +298,6 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy {
return `Total: ${new Intl.NumberFormat(this.locale, { return `Total: ${new Intl.NumberFormat(this.locale, {
currency: this.currency, currency: this.currency,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Only supported from ES2020 or later
currencyDisplay: 'code', currencyDisplay: 'code',
style: 'currency' style: 'currency'
}).format(totalAmount)}`; }).format(totalAmount)}`;
@ -434,12 +435,16 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy {
} }
private getPeriodsToRetire(): number { private getPeriodsToRetire(): number {
if (this.calculatorForm.get('projectedTotalAmount')?.value) { const projectedTotalAmount = this.calculatorForm.get(
'projectedTotalAmount'
)?.value;
if (projectedTotalAmount) {
let periods = this.fireCalculatorService.calculatePeriodsToRetire({ let periods = this.fireCalculatorService.calculatePeriodsToRetire({
P: this.getP(), P: this.getP(),
PMT: this.getPMT(), PMT: this.getPMT(),
r: this.getR(), r: this.getR(),
totalAmount: this.calculatorForm.get('projectedTotalAmount')!.value totalAmount: projectedTotalAmount
}); });
if (periods === Infinity) { if (periods === Infinity) {
@ -460,13 +465,17 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy {
} }
} }
private getPMT(): number { private getPMT() {
return this.calculatorForm.get('paymentPerPeriod')!.value; return this.calculatorForm.get('paymentPerPeriod')?.value ?? 0;
} }
private getProjectedTotalAmount() { private getProjectedTotalAmount() {
if (this.calculatorForm.get('projectedTotalAmount')?.value) { const projectedTotalAmount = this.calculatorForm.get(
return this.calculatorForm.get('projectedTotalAmount')!.value; 'projectedTotalAmount'
)?.value;
if (!isNil(projectedTotalAmount)) {
return projectedTotalAmount;
} }
const { totalAmount } = const { totalAmount } =
@ -481,12 +490,12 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy {
} }
private getR() { private getR() {
return this.calculatorForm.get('annualInterestRate')!.value / 100; return (this.calculatorForm.get('annualInterestRate')?.value ?? 0) / 100;
} }
private getRetirementDate(): Date | undefined { private getRetirementDate(): Date | undefined {
if (this.periodsToRetire === Number.MAX_SAFE_INTEGER) { if (this.periodsToRetire === Number.MAX_SAFE_INTEGER) {
return undefined; return this.DEFAULT_RETIREMENT_DATE;
} }
const monthsToRetire = this.periodsToRetire % 12; const monthsToRetire = this.periodsToRetire % 12;

227
package-lock.json

@ -1,12 +1,12 @@
{ {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.242.0", "version": "2.243.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.242.0", "version": "2.243.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {
@ -27,15 +27,15 @@
"@ionic/angular": "8.7.8", "@ionic/angular": "8.7.8",
"@keyv/redis": "4.4.0", "@keyv/redis": "4.4.0",
"@nestjs/bull": "11.0.4", "@nestjs/bull": "11.0.4",
"@nestjs/cache-manager": "3.0.1", "@nestjs/cache-manager": "3.1.0",
"@nestjs/common": "11.1.8", "@nestjs/common": "11.1.14",
"@nestjs/config": "4.0.2", "@nestjs/config": "4.0.3",
"@nestjs/core": "11.1.8", "@nestjs/core": "11.1.14",
"@nestjs/event-emitter": "3.0.1", "@nestjs/event-emitter": "3.0.1",
"@nestjs/jwt": "11.0.1", "@nestjs/jwt": "11.0.2",
"@nestjs/passport": "11.0.5", "@nestjs/passport": "11.0.5",
"@nestjs/platform-express": "11.1.8", "@nestjs/platform-express": "11.1.14",
"@nestjs/schedule": "6.0.1", "@nestjs/schedule": "6.1.1",
"@nestjs/serve-static": "5.0.4", "@nestjs/serve-static": "5.0.4",
"@openrouter/ai-sdk-provider": "0.7.2", "@openrouter/ai-sdk-provider": "0.7.2",
"@prisma/client": "6.19.0", "@prisma/client": "6.19.0",
@ -107,7 +107,7 @@
"@eslint/eslintrc": "3.3.1", "@eslint/eslintrc": "3.3.1",
"@eslint/js": "9.35.0", "@eslint/js": "9.35.0",
"@nestjs/schematics": "11.0.9", "@nestjs/schematics": "11.0.9",
"@nestjs/testing": "11.1.8", "@nestjs/testing": "11.1.14",
"@nx/angular": "22.4.5", "@nx/angular": "22.4.5",
"@nx/eslint-plugin": "22.4.5", "@nx/eslint-plugin": "22.4.5",
"@nx/jest": "22.4.5", "@nx/jest": "22.4.5",
@ -3617,6 +3617,16 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@borewit/text-codec": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.1.tgz",
"integrity": "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Borewit"
}
},
"node_modules/@braintree/sanitize-url": { "node_modules/@braintree/sanitize-url": {
"version": "7.1.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz", "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz",
@ -7531,9 +7541,9 @@
} }
}, },
"node_modules/@nestjs/cache-manager": { "node_modules/@nestjs/cache-manager": {
"version": "3.0.1", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-3.0.1.tgz", "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-3.1.0.tgz",
"integrity": "sha512-4UxTnR0fsmKL5YDalU2eLFVnL+OBebWUpX+hEduKGncrVKH4PPNoiRn1kXyOCjmzb0UvWgqubpssNouc8e0MCw==", "integrity": "sha512-pEIqYZrBcE8UdkJmZRduurvoUfdU+3kRPeO1R2muiMbZnRuqlki5klFFNllO9LyYWzrx98bd1j0PSPKSJk1Wbw==",
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
"@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0", "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0",
@ -7544,12 +7554,12 @@
} }
}, },
"node_modules/@nestjs/common": { "node_modules/@nestjs/common": {
"version": "11.1.8", "version": "11.1.14",
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.8.tgz", "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.14.tgz",
"integrity": "sha512-bbsOqwld/GdBfiRNc4nnjyWWENDEicq4SH+R5AuYatvf++vf1x5JIsHB1i1KtfZMD3eRte0D4K9WXuAYil6XAg==", "integrity": "sha512-IN/tlqd7Nl9gl6f0jsWEuOrQDaCI9vHzxv0fisHysfBQzfQIkqlv5A7w4Qge02BUQyczXT9HHPgHtWHCxhjRng==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"file-type": "21.0.0", "file-type": "21.3.0",
"iterare": "1.2.1", "iterare": "1.2.1",
"load-esm": "1.0.3", "load-esm": "1.0.3",
"tslib": "2.8.1", "tslib": "2.8.1",
@ -7575,57 +7585,24 @@
} }
}, },
"node_modules/@nestjs/config": { "node_modules/@nestjs/config": {
"version": "4.0.2", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/@nestjs/config/-/config-4.0.2.tgz", "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-4.0.3.tgz",
"integrity": "sha512-McMW6EXtpc8+CwTUwFdg6h7dYcBUpH5iUILCclAsa+MbCEvC9ZKu4dCHRlJqALuhjLw97pbQu62l4+wRwGeZqA==", "integrity": "sha512-FQ3M3Ohqfl+nHAn5tp7++wUQw0f2nAk+SFKe8EpNRnIifPqvfJP6JQxPKtFLMOHbyer4X646prFG4zSRYEssQQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"dotenv": "16.4.7", "dotenv": "17.2.3",
"dotenv-expand": "12.0.1", "dotenv-expand": "12.0.3",
"lodash": "4.17.21" "lodash": "4.17.23"
}, },
"peerDependencies": { "peerDependencies": {
"@nestjs/common": "^10.0.0 || ^11.0.0", "@nestjs/common": "^10.0.0 || ^11.0.0",
"rxjs": "^7.1.0" "rxjs": "^7.1.0"
} }
}, },
"node_modules/@nestjs/config/node_modules/dotenv": {
"version": "16.4.7",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
"integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/@nestjs/config/node_modules/dotenv-expand": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-12.0.1.tgz",
"integrity": "sha512-LaKRbou8gt0RNID/9RoI+J2rvXsBRPMV7p+ElHlPhcSARbCPDYcYG2s1TIzAfWv4YSgyY5taidWzzs31lNV3yQ==",
"license": "BSD-2-Clause",
"dependencies": {
"dotenv": "^16.4.5"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/@nestjs/config/node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"license": "MIT"
},
"node_modules/@nestjs/core": { "node_modules/@nestjs/core": {
"version": "11.1.8", "version": "11.1.14",
"resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.8.tgz", "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.14.tgz",
"integrity": "sha512-7riWfmTmMhCJHZ5ZiaG+crj4t85IPCq/wLRuOUSigBYyFT2JZj0lVHtAdf4Davp9ouNI8GINBDt9h9b5Gz9nTw==", "integrity": "sha512-7OXPPMoDr6z+5NkoQKu4hOhfjz/YYqM3bNilPqv1WVFWrzSmuNXxvhbX69YMmNmRYascPXiwESqf5jJdjKXEww==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -7677,13 +7654,13 @@
} }
}, },
"node_modules/@nestjs/jwt": { "node_modules/@nestjs/jwt": {
"version": "11.0.1", "version": "11.0.2",
"resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-11.0.1.tgz", "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-11.0.2.tgz",
"integrity": "sha512-HXSsc7SAnCnjA98TsZqrE7trGtHDnYXWp4Ffy6LwSmck1QvbGYdMzBquXofX5l6tIRpeY4Qidl2Ti2CVG77Pdw==", "integrity": "sha512-rK8aE/3/Ma45gAWfCksAXUNbOoSOUudU0Kn3rT39htPF7wsYXtKfjALKeKKJbFrIWbLjsbqfXX5bIJNvgBugGA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/jsonwebtoken": "9.0.10", "@types/jsonwebtoken": "9.0.10",
"jsonwebtoken": "9.0.2" "jsonwebtoken": "9.0.3"
}, },
"peerDependencies": { "peerDependencies": {
"@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0"
@ -7700,13 +7677,13 @@
} }
}, },
"node_modules/@nestjs/platform-express": { "node_modules/@nestjs/platform-express": {
"version": "11.1.8", "version": "11.1.14",
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.8.tgz", "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.14.tgz",
"integrity": "sha512-rL6pZH9BW7BnL5X2eWbJMtt86uloAKjFgyY5+L2UkizgfEp7rgAs0+Z1z0BcW2Pgu5+q8O7RKPNyHJ/9ZNz/ZQ==", "integrity": "sha512-Fs+/j+mBSBSXErOQJ/YdUn/HqJGSJ4pGfiJyYOyz04l42uNVnqEakvu1kXLbxMabR6vd6/h9d6Bi4tso9p7o4Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"cors": "2.8.5", "cors": "2.8.6",
"express": "5.1.0", "express": "5.2.1",
"multer": "2.0.2", "multer": "2.0.2",
"path-to-regexp": "8.3.0", "path-to-regexp": "8.3.0",
"tslib": "2.8.1" "tslib": "2.8.1"
@ -7721,12 +7698,12 @@
} }
}, },
"node_modules/@nestjs/schedule": { "node_modules/@nestjs/schedule": {
"version": "6.0.1", "version": "6.1.1",
"resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-6.0.1.tgz", "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-6.1.1.tgz",
"integrity": "sha512-v3yO6cSPAoBSSyH67HWnXHzuhPhSNZhRmLY38JvCt2sqY8sPMOODpcU1D79iUMFf7k16DaMEbL4Mgx61ZhiC8Q==", "integrity": "sha512-kQl1RRgi02GJ0uaUGCrXHCcwISsCsJDciCKe38ykJZgnAeeoeVWs8luWtBo4AqAAXm4nS5K8RlV0smHUJ4+2FA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"cron": "4.3.3" "cron": "4.4.0"
}, },
"peerDependencies": { "peerDependencies": {
"@nestjs/common": "^10.0.0 || ^11.0.0", "@nestjs/common": "^10.0.0 || ^11.0.0",
@ -7910,9 +7887,9 @@
} }
}, },
"node_modules/@nestjs/testing": { "node_modules/@nestjs/testing": {
"version": "11.1.8", "version": "11.1.14",
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.8.tgz", "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.14.tgz",
"integrity": "sha512-E6K+0UTKztcPxJzLnQa7S34lFjZbrj3Z1r7c5y5WDrL1m5HD1H4AeyBhicHgdaFmxjLAva2bq0sYKy/S7cdeYA==", "integrity": "sha512-cQxX0ronsTbpfHz8/LYOVWXxoTxv6VoxrnuZoQaVX7QV2PSMqxWE7/9jSQR0GcqAFUEmFP34c6EJqfkjfX/k4Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -12408,14 +12385,13 @@
} }
}, },
"node_modules/@tokenizer/inflate": { "node_modules/@tokenizer/inflate": {
"version": "0.2.7", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
"integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"debug": "^4.4.0", "debug": "^4.4.3",
"fflate": "^0.8.2", "token-types": "^6.1.1"
"token-types": "^6.0.0"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=18"
@ -16984,9 +16960,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/cors": { "node_modules/cors": {
"version": "2.8.5", "version": "2.8.6",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"object-assign": "^4", "object-assign": "^4",
@ -16994,6 +16970,10 @@
}, },
"engines": { "engines": {
"node": ">= 0.10" "node": ">= 0.10"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
} }
}, },
"node_modules/corser": { "node_modules/corser": {
@ -17073,9 +17053,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/cron": { "node_modules/cron": {
"version": "4.3.3", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/cron/-/cron-4.3.3.tgz", "resolved": "https://registry.npmjs.org/cron/-/cron-4.4.0.tgz",
"integrity": "sha512-B/CJj5yL3sjtlun6RtYHvoSB26EmQ2NUmhq9ZiJSyKIM4K/fqfh9aelDFlIayD2YMeFZqWLi9hHV+c+pq2Djkw==", "integrity": "sha512-fkdfq+b+AHI4cKdhZlppHveI/mgz2qpiYxcm+t5E5TsxX7QrLS1VE0+7GENEk9z0EeGPcpSciGv6ez24duWhwQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/luxon": "~3.7.0", "@types/luxon": "~3.7.0",
@ -17083,6 +17063,10 @@
}, },
"engines": { "engines": {
"node": ">=18.x" "node": ">=18.x"
},
"funding": {
"type": "ko-fi",
"url": "https://ko-fi.com/intcreator"
} }
}, },
"node_modules/cron-parser": { "node_modules/cron-parser": {
@ -19852,18 +19836,19 @@
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/express": { "node_modules/express": {
"version": "5.1.0", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"accepts": "^2.0.0", "accepts": "^2.0.0",
"body-parser": "^2.2.0", "body-parser": "^2.2.1",
"content-disposition": "^1.0.0", "content-disposition": "^1.0.0",
"content-type": "^1.0.5", "content-type": "^1.0.5",
"cookie": "^0.7.1", "cookie": "^0.7.1",
"cookie-signature": "^1.2.1", "cookie-signature": "^1.2.1",
"debug": "^4.4.0", "debug": "^4.4.0",
"depd": "^2.0.0",
"encodeurl": "^2.0.0", "encodeurl": "^2.0.0",
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
"etag": "^1.8.1", "etag": "^1.8.1",
@ -20129,12 +20114,6 @@
"filenamify-url": "2.1.2" "filenamify-url": "2.1.2"
} }
}, },
"node_modules/fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
"license": "MIT"
},
"node_modules/figures": { "node_modules/figures": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
@ -20175,14 +20154,14 @@
} }
}, },
"node_modules/file-type": { "node_modules/file-type": {
"version": "21.0.0", "version": "21.3.0",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz", "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.0.tgz",
"integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==", "integrity": "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tokenizer/inflate": "^0.2.7", "@tokenizer/inflate": "^0.4.1",
"strtok3": "^10.2.2", "strtok3": "^10.3.4",
"token-types": "^6.0.0", "token-types": "^6.1.1",
"uint8array-extras": "^1.4.0" "uint8array-extras": "^1.4.0"
}, },
"engines": { "engines": {
@ -24592,12 +24571,12 @@
} }
}, },
"node_modules/jsonwebtoken": { "node_modules/jsonwebtoken": {
"version": "9.0.2", "version": "9.0.3",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"jws": "^3.2.2", "jws": "^4.0.1",
"lodash.includes": "^4.3.0", "lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3", "lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4", "lodash.isinteger": "^4.0.4",
@ -24613,27 +24592,6 @@
"npm": ">=6" "npm": ">=6"
} }
}, },
"node_modules/jsonwebtoken/node_modules/jwa": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
"integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jsonwebtoken/node_modules/jws": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz",
"integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==",
"license": "MIT",
"dependencies": {
"jwa": "^1.4.2",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jsonwebtoken/node_modules/ms": { "node_modules/jsonwebtoken/node_modules/ms": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@ -32900,11 +32858,12 @@
} }
}, },
"node_modules/token-types": { "node_modules/token-types": {
"version": "6.0.4", "version": "6.1.2",
"resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.4.tgz", "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz",
"integrity": "sha512-MD9MjpVNhVyH4fyd5rKphjvt/1qj+PtQUz65aFqAZA6XniWAuSFRjLk3e2VALEFlh9OwBpXUN7rfeqSnT/Fmkw==", "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@borewit/text-codec": "^0.2.1",
"@tokenizer/token": "^0.3.0", "@tokenizer/token": "^0.3.0",
"ieee754": "^1.2.1" "ieee754": "^1.2.1"
}, },
@ -33690,9 +33649,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/uint8array-extras": { "node_modules/uint8array-extras": {
"version": "1.4.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.4.0.tgz", "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz",
"integrity": "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==", "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">=18"

18
package.json

@ -1,6 +1,6 @@
{ {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.242.0", "version": "2.243.0",
"homepage": "https://ghostfol.io", "homepage": "https://ghostfol.io",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"repository": "https://github.com/ghostfolio/ghostfolio", "repository": "https://github.com/ghostfolio/ghostfolio",
@ -72,15 +72,15 @@
"@ionic/angular": "8.7.8", "@ionic/angular": "8.7.8",
"@keyv/redis": "4.4.0", "@keyv/redis": "4.4.0",
"@nestjs/bull": "11.0.4", "@nestjs/bull": "11.0.4",
"@nestjs/cache-manager": "3.0.1", "@nestjs/cache-manager": "3.1.0",
"@nestjs/common": "11.1.8", "@nestjs/common": "11.1.14",
"@nestjs/config": "4.0.2", "@nestjs/config": "4.0.3",
"@nestjs/core": "11.1.8", "@nestjs/core": "11.1.14",
"@nestjs/event-emitter": "3.0.1", "@nestjs/event-emitter": "3.0.1",
"@nestjs/jwt": "11.0.1", "@nestjs/jwt": "11.0.2",
"@nestjs/passport": "11.0.5", "@nestjs/passport": "11.0.5",
"@nestjs/platform-express": "11.1.8", "@nestjs/platform-express": "11.1.14",
"@nestjs/schedule": "6.0.1", "@nestjs/schedule": "6.1.1",
"@nestjs/serve-static": "5.0.4", "@nestjs/serve-static": "5.0.4",
"@openrouter/ai-sdk-provider": "0.7.2", "@openrouter/ai-sdk-provider": "0.7.2",
"@prisma/client": "6.19.0", "@prisma/client": "6.19.0",
@ -152,7 +152,7 @@
"@eslint/eslintrc": "3.3.1", "@eslint/eslintrc": "3.3.1",
"@eslint/js": "9.35.0", "@eslint/js": "9.35.0",
"@nestjs/schematics": "11.0.9", "@nestjs/schematics": "11.0.9",
"@nestjs/testing": "11.1.8", "@nestjs/testing": "11.1.14",
"@nx/angular": "22.4.5", "@nx/angular": "22.4.5",
"@nx/eslint-plugin": "22.4.5", "@nx/eslint-plugin": "22.4.5",
"@nx/jest": "22.4.5", "@nx/jest": "22.4.5",

Loading…
Cancel
Save