diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bbf0a08dd..c9937fcb31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Extended the emergency fund dialog in the portfolio summary to include the currency suffix - Migrated the client to the code generated by the new `prisma-client` generator of _Prisma_ +- Migrated from `lodash` to `lodash-es` ### Fixed diff --git a/apps/api/src/app/account-balance/account-balance.service.ts b/apps/api/src/app/account-balance/account-balance.service.ts index 3823498df3..ad990c66bd 100644 --- a/apps/api/src/app/account-balance/account-balance.service.ts +++ b/apps/api/src/app/account-balance/account-balance.service.ts @@ -24,7 +24,7 @@ import { EventEmitter2 } from '@nestjs/event-emitter'; import { AccountBalance, Prisma } from '@prisma/client'; import { Big } from 'big.js'; import { endOfToday, format, min, parseISO } from 'date-fns'; -import { groupBy } from 'lodash'; +import { groupBy } from 'lodash-es'; @Injectable() export class AccountBalanceService { diff --git a/apps/api/src/app/account/account.service.ts b/apps/api/src/app/account/account.service.ts index 59315602a8..d1a895a5a3 100644 --- a/apps/api/src/app/account/account.service.ts +++ b/apps/api/src/app/account/account.service.ts @@ -28,7 +28,7 @@ import { } from '@prisma/client'; import { Big } from 'big.js'; import { format } from 'date-fns'; -import { groupBy, isNil } from 'lodash'; +import { groupBy, isNil } from 'lodash-es'; import { CashDetails } from './interfaces/cash-details.interface'; diff --git a/apps/api/src/app/activities/activities-filter.dto.ts b/apps/api/src/app/activities/activities-filter.dto.ts index 0c56aacc85..17385148cc 100644 --- a/apps/api/src/app/activities/activities-filter.dto.ts +++ b/apps/api/src/app/activities/activities-filter.dto.ts @@ -5,7 +5,7 @@ import { DateRange } from '@ghostfolio/common/types'; import { Type as ActivityType } from '@prisma/client'; import { Transform, TransformFnParams } from 'class-transformer'; import { IsEnum, IsOptional, Matches } from 'class-validator'; -import { isString } from 'lodash'; +import { isString } from 'lodash-es'; export class ActivitiesFilterDto extends FilterDto { @IsEnum(ActivityType, { each: true }) diff --git a/apps/api/src/app/activities/activities.service.ts b/apps/api/src/app/activities/activities.service.ts index ecc2296a90..59d1ba9c33 100644 --- a/apps/api/src/app/activities/activities.service.ts +++ b/apps/api/src/app/activities/activities.service.ts @@ -60,7 +60,7 @@ import { Type as ActivityType } from '@prisma/client'; import { Big } from 'big.js'; -import { groupBy, uniqBy } from 'lodash'; +import { groupBy, uniqBy } from 'lodash-es'; import { randomUUID } from 'node:crypto'; @Injectable() diff --git a/apps/api/src/app/asset/asset.controller.ts b/apps/api/src/app/asset/asset.controller.ts index 49afb43d71..352d3e18b1 100644 --- a/apps/api/src/app/asset/asset.controller.ts +++ b/apps/api/src/app/asset/asset.controller.ts @@ -5,7 +5,7 @@ import type { AssetResponse } from '@ghostfolio/common/interfaces'; import { Controller, Get, Param, UseInterceptors } from '@nestjs/common'; import { DataSource } from '@prisma/client'; -import { pick } from 'lodash'; +import { pick } from 'lodash-es'; @Controller('asset') export class AssetController { diff --git a/apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts b/apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts index e9aad6911f..4a2507e697 100644 --- a/apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts +++ b/apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts @@ -29,7 +29,7 @@ import { MarketDataPreset } from '@ghostfolio/common/types'; import { Injectable, Logger, NotFoundException } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { AssetClass, AssetSubClass, DataSource, Prisma } from '@prisma/client'; -import { groupBy } from 'lodash'; +import { groupBy } from 'lodash-es'; @Injectable() export class AssetProfilesService { diff --git a/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts b/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts index beff7ffa60..908db59b7f 100644 --- a/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts +++ b/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts @@ -14,7 +14,7 @@ import { DateRange } from '@ghostfolio/common/types'; import { Injectable, Logger } from '@nestjs/common'; import { format, isSameDay } from 'date-fns'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; @Injectable() export class BenchmarksService { diff --git a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts index ec0eeeb868..4042241449 100644 --- a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts +++ b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts @@ -40,7 +40,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { DataSource, SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; import { addMilliseconds, isBefore } from 'date-fns'; -import { isEmpty } from 'lodash'; +import { isEmpty } from 'lodash-es'; @Injectable() export class GhostfolioService { diff --git a/apps/api/src/app/export/export.service.ts b/apps/api/src/app/export/export.service.ts index 35db209935..db08f62052 100644 --- a/apps/api/src/app/export/export.service.ts +++ b/apps/api/src/app/export/export.service.ts @@ -11,7 +11,7 @@ import { import { Injectable } from '@nestjs/common'; import { Platform, Prisma, Type as ActivityType } from '@prisma/client'; -import { groupBy, uniqBy } from 'lodash'; +import { groupBy, uniqBy } from 'lodash-es'; @Injectable() export class ExportService { diff --git a/apps/api/src/app/export/get-export.dto.ts b/apps/api/src/app/export/get-export.dto.ts index 5fc3c81baa..524c357112 100644 --- a/apps/api/src/app/export/get-export.dto.ts +++ b/apps/api/src/app/export/get-export.dto.ts @@ -2,7 +2,7 @@ import { ActivitiesFilterDto } from '@ghostfolio/api/app/activities/activities-f import { Transform, TransformFnParams } from 'class-transformer'; import { IsOptional, IsUUID } from 'class-validator'; -import { isString } from 'lodash'; +import { isString } from 'lodash-es'; export class GetExportDto extends ActivitiesFilterDto { @IsOptional() diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index 5f202f4ac4..5afa4c33dd 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -47,7 +47,7 @@ import { Account, DataSource, Prisma } from '@prisma/client'; import { Big } from 'big.js'; import { isISIN } from 'class-validator'; import { isSameSecond, parseISO } from 'date-fns'; -import { omit, uniqBy } from 'lodash'; +import { omit, uniqBy } from 'lodash-es'; import { randomUUID } from 'node:crypto'; import { ImportValidationError } from './errors/import-validation.error'; diff --git a/apps/api/src/app/info/info.service.ts b/apps/api/src/app/info/info.service.ts index a0759b1698..2a7382446c 100644 --- a/apps/api/src/app/info/info.service.ts +++ b/apps/api/src/app/info/info.service.ts @@ -26,7 +26,7 @@ import { Injectable } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { MarketData } from '@prisma/client'; import { subDays } from 'date-fns'; -import { isNil } from 'lodash'; +import { isNil } from 'lodash-es'; @Injectable() export class InfoService { diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index d868b65b3f..e03b530258 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -72,7 +72,7 @@ import { startOfYear, subDays } from 'date-fns'; -import { groupBy, sortBy, uniqBy } from 'lodash'; +import { groupBy, sortBy, uniqBy } from 'lodash-es'; export abstract class PortfolioCalculator { protected static readonly ENABLE_LOGGING = false; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts index 2b7b4e6dce..c0b7337350 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts @@ -32,7 +32,7 @@ import { isBefore, isThisYear } from 'date-fns'; -import { sum } from 'lodash'; +import { sum } from 'lodash-es'; export class RoaiPortfolioCalculator extends PortfolioCalculator { protected calculateOverallPerformance( diff --git a/apps/api/src/app/portfolio/current-rate.service.ts b/apps/api/src/app/portfolio/current-rate.service.ts index 79363c6344..80d37259a4 100644 --- a/apps/api/src/app/portfolio/current-rate.service.ts +++ b/apps/api/src/app/portfolio/current-rate.service.ts @@ -14,7 +14,7 @@ import { import { Injectable } from '@nestjs/common'; import { isBefore, isToday } from 'date-fns'; -import { isEmpty, uniqBy } from 'lodash'; +import { isEmpty, uniqBy } from 'lodash-es'; import { GetValueObject } from './interfaces/get-value-object.interface'; import { GetValuesObject } from './interfaces/get-values-object.interface'; diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 7350f5fc01..72c5b5946a 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -104,7 +104,7 @@ import { set, startOfDay } from 'date-fns'; -import { groupBy } from 'lodash'; +import { groupBy } from 'lodash-es'; import { PortfolioCalculator } from './calculator/portfolio-calculator'; import { PortfolioCalculatorFactory } from './calculator/portfolio-calculator.factory'; diff --git a/apps/api/src/app/symbol/symbol.controller.ts b/apps/api/src/app/symbol/symbol.controller.ts index 9d8abb47ba..cf26d39d54 100644 --- a/apps/api/src/app/symbol/symbol.controller.ts +++ b/apps/api/src/app/symbol/symbol.controller.ts @@ -25,7 +25,7 @@ import { AuthGuard } from '@nestjs/passport'; import { DataSource } from '@prisma/client'; import { isValid, parseISO } from 'date-fns'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; -import { isEmpty } from 'lodash'; +import { isEmpty } from 'lodash-es'; import { GetLookupDto } from './get-lookup.dto'; import { SymbolService } from './symbol.service'; diff --git a/apps/api/src/app/user/user.controller.ts b/apps/api/src/app/user/user.controller.ts index ae9e7d680b..32ac353351 100644 --- a/apps/api/src/app/user/user.controller.ts +++ b/apps/api/src/app/user/user.controller.ts @@ -53,7 +53,7 @@ import { AuthGuard } from '@nestjs/passport'; import { Throttle } from '@nestjs/throttler'; import { User as UserModel } from '@prisma/client'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; -import { merge, size } from 'lodash'; +import { merge, size } from 'lodash-es'; import { UserService } from './user.service'; diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index a74e32ca93..2e54a7ddc3 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -46,7 +46,7 @@ import { EventEmitter2 } from '@nestjs/event-emitter'; import { InjectThrottlerStorage, ThrottlerStorage } from '@nestjs/throttler'; import { Prisma, Role, User } from '@prisma/client'; import { differenceInDays, subDays } from 'date-fns'; -import { isNil, without } from 'lodash'; +import { isNil, without } from 'lodash-es'; import { createHmac } from 'node:crypto'; @Injectable() diff --git a/apps/api/src/dtos/filter.dto.ts b/apps/api/src/dtos/filter.dto.ts index 09206984ab..84d9ffc0d0 100644 --- a/apps/api/src/dtos/filter.dto.ts +++ b/apps/api/src/dtos/filter.dto.ts @@ -9,7 +9,7 @@ import { IsUUID, MaxLength } from 'class-validator'; -import { isString } from 'lodash'; +import { isString } from 'lodash-es'; export class FilterDto { @IsOptional() diff --git a/apps/api/src/helper/activity.helper.ts b/apps/api/src/helper/activity.helper.ts index b281106c77..f7cb20505e 100644 --- a/apps/api/src/helper/activity.helper.ts +++ b/apps/api/src/helper/activity.helper.ts @@ -5,7 +5,7 @@ import { import { Prisma, Type as ActivityType } from '@prisma/client'; import { endOfToday, isAfter } from 'date-fns'; -import { uniqBy } from 'lodash'; +import { uniqBy } from 'lodash-es'; export const WHERE_ACTIVITY_NOT_DRAFT: Prisma.OrderWhereInput = { tags: { diff --git a/apps/api/src/helper/object.helper.ts b/apps/api/src/helper/object.helper.ts index 350d5fe04a..c040c5e0fc 100644 --- a/apps/api/src/helper/object.helper.ts +++ b/apps/api/src/helper/object.helper.ts @@ -1,6 +1,6 @@ import fastRedact from 'fast-redact'; import jsonpath from 'jsonpath'; -import { cloneDeep, isObject } from 'lodash'; +import { cloneDeep, isObject } from 'lodash-es'; export function hasNotDefinedValuesInObject(aObject: Object): boolean { for (const key in aObject) { diff --git a/apps/api/src/models/rule.ts b/apps/api/src/models/rule.ts index 4985b26477..f7f6c53637 100644 --- a/apps/api/src/models/rule.ts +++ b/apps/api/src/models/rule.ts @@ -7,7 +7,7 @@ import { } from '@ghostfolio/common/interfaces'; import { Big } from 'big.js'; -import { groupBy } from 'lodash'; +import { groupBy } from 'lodash-es'; import { EvaluationResult } from './interfaces/evaluation-result.interface'; import { RuleInterface } from './interfaces/rule.interface'; diff --git a/apps/api/src/services/benchmark/benchmark.service.ts b/apps/api/src/services/benchmark/benchmark.service.ts index 953939caac..4ea27b2f2e 100644 --- a/apps/api/src/services/benchmark/benchmark.service.ts +++ b/apps/api/src/services/benchmark/benchmark.service.ts @@ -23,7 +23,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; import { addHours, isPast, subDays } from 'date-fns'; -import { round, uniqBy } from 'lodash'; +import { round, uniqBy } from 'lodash-es'; import ms from 'ms'; import { BenchmarkValue } from './interfaces/benchmark-value.interface'; 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 87c1e85c61..cfacab3231 100644 --- a/apps/api/src/services/data-provider/data-provider.service.ts +++ b/apps/api/src/services/data-provider/data-provider.service.ts @@ -42,7 +42,7 @@ import { Inject, Injectable, Logger, OnModuleInit } from '@nestjs/common'; import { DataSource, MarketData, Prisma, SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; import { eachDayOfInterval, format, isValid } from 'date-fns'; -import { groupBy, isEmpty, isNumber, omit, uniqWith } from 'lodash'; +import { groupBy, isEmpty, isNumber, omit, uniqWith } from 'lodash-es'; import ms from 'ms'; import { AssetProfileInvalidError } from './errors/asset-profile-invalid.error'; diff --git a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts index 6bc003fc23..7dbb3b859c 100644 --- a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts +++ b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts @@ -31,7 +31,7 @@ import { SymbolProfile } from '@prisma/client'; import { addDays, format, isSameDay, isToday } from 'date-fns'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; @Injectable() export class EodHistoricalDataService 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 7c840b5fc6..a8f1c6287c 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 @@ -47,7 +47,7 @@ import { isSameDay, parseISO } from 'date-fns'; -import { isArray, uniqBy } from 'lodash'; +import { isArray, uniqBy } from 'lodash-es'; @Injectable() export class FinancialModelingPrepService 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 ca6357e257..d2b741d372 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 @@ -24,7 +24,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { DataSource, SymbolProfile } from '@prisma/client'; import { addDays, format, isSameDay } from 'date-fns'; import { ReasonPhrases, StatusCodes } from 'http-status-codes'; -import { uniqBy } from 'lodash'; +import { uniqBy } from 'lodash-es'; import YahooFinance from 'yahoo-finance2'; import type { ChartResultArray } from 'yahoo-finance2/modules/chart'; import type { diff --git a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts index 0d7e98e2e0..824149e74f 100644 --- a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts +++ b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts @@ -26,7 +26,7 @@ import { isToday, subDays } from 'date-fns'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; import ms from 'ms'; import { ExchangeRatesByCurrency } from './interfaces/exchange-rate-data.interface'; diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts index 4cbe6969ae..3a98757591 100644 --- a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts +++ b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts @@ -33,7 +33,7 @@ import { Inject, Injectable, Logger } from '@nestjs/common'; import { Prisma } from '@prisma/client'; import { Job, JobOptions, Queue } from 'bull'; import { format, min, subDays, subMilliseconds, subYears } from 'date-fns'; -import { isEmpty } from 'lodash'; +import { isEmpty } from 'lodash-es'; import ms, { StringValue } from 'ms'; @Injectable() diff --git a/apps/api/src/services/twitter-bot/twitter-bot.service.ts b/apps/api/src/services/twitter-bot/twitter-bot.service.ts index 2dbed82d21..6282b4363b 100644 --- a/apps/api/src/services/twitter-bot/twitter-bot.service.ts +++ b/apps/api/src/services/twitter-bot/twitter-bot.service.ts @@ -10,7 +10,7 @@ import { import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; import { isWeekend } from 'date-fns'; -import { round } from 'lodash'; +import { round } from 'lodash-es'; import { TwitterApi, TwitterApiReadWrite } from 'twitter-api-v2'; @Injectable() diff --git a/apps/client/jest.config.ts b/apps/client/jest.config.ts index 26d772e11f..d60a24ae4f 100644 --- a/apps/client/jest.config.ts +++ b/apps/client/jest.config.ts @@ -18,6 +18,6 @@ export default { } ] }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + transformIgnorePatterns: ['node_modules/(?!.*.mjs$|lodash-es/)'], preset: '../../jest.preset.js' }; diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts index b8c7f16dbc..44f7280473 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts @@ -55,7 +55,7 @@ import { readerOutline, swapVerticalOutline } from 'ionicons/icons'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { filter, forkJoin } from 'rxjs'; diff --git a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts index fd90bff2c1..e8e3a21255 100644 --- a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts +++ b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts @@ -49,7 +49,7 @@ import { removeCircleOutline, timeOutline } from 'ionicons/icons'; -import { get } from 'lodash'; +import { get } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts index 154211b918..ba119b565f 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts @@ -106,7 +106,7 @@ import { serverOutline, trashOutline } from 'ionicons/icons'; -import { isBoolean } from 'lodash'; +import { isBoolean } from 'lodash-es'; import ms from 'ms'; import { EMPTY } from 'rxjs'; import { catchError } from 'rxjs/operators'; diff --git a/apps/client/src/app/components/admin-settings/admin-settings.component.ts b/apps/client/src/app/components/admin-settings/admin-settings.component.ts index b0c3dc2d22..d49f3fb0aa 100644 --- a/apps/client/src/app/components/admin-settings/admin-settings.component.ts +++ b/apps/client/src/app/components/admin-settings/admin-settings.component.ts @@ -42,7 +42,7 @@ import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { ellipsisHorizontal, trashOutline } from 'ionicons/icons'; -import { get } from 'lodash'; +import { get } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { catchError, filter, of } from 'rxjs'; diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts index 4a16c1a4e2..8c3ec2206e 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts @@ -82,7 +82,7 @@ import { swapVerticalOutline, walletOutline } from 'ionicons/icons'; -import { isNumber, round, uniqBy } from 'lodash'; +import { isNumber, round, uniqBy } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { filter, switchMap } from 'rxjs/operators'; diff --git a/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts b/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts index a48d77a2dd..4f7f35dd1e 100644 --- a/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts +++ b/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts @@ -23,7 +23,7 @@ import { IonIcon } from '@ionic/angular/standalone'; import { CountUp } from 'countup.js'; import { addIcons } from 'ionicons'; import { timeOutline } from 'ionicons/icons'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts index feedddacae..13686624f7 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts @@ -23,7 +23,7 @@ import { ellipsisHorizontalCircleOutline, informationCircleOutline } from 'ionicons/icons'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ diff --git a/apps/client/src/app/pages/api/api-page.component.ts b/apps/client/src/app/pages/api/api-page.component.ts index 8b80370e8d..36c780a04e 100644 --- a/apps/client/src/app/pages/api/api-page.component.ts +++ b/apps/client/src/app/pages/api/api-page.component.ts @@ -32,7 +32,7 @@ import { import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatCardModule } from '@angular/material/card'; import { format, startOfYear } from 'date-fns'; -import { isObject } from 'lodash'; +import { isObject } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { catchError, map, Observable, of, OperatorFunction } from 'rxjs'; diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts index 26255f2061..a1a9bddd6b 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -51,7 +51,7 @@ import { MatTableDataSource } from '@angular/material/table'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { cloudUploadOutline, warningOutline } from 'ionicons/icons'; -import { isArray, sortBy } from 'lodash'; +import { isArray, sortBy } from 'lodash-es'; import ms from 'ms'; import { ImportStep } from './enums/import-step'; diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts index 6d67b0253c..487bcf6086 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -53,7 +53,7 @@ import { MatCardModule } from '@angular/material/card'; import { MatDialog } from '@angular/material/dialog'; import { MatProgressBarModule } from '@angular/material/progress-bar'; import { ActivatedRoute, Router } from '@angular/router'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; import { DeviceDetectorService } from 'ngx-device-detector'; import { filter, switchMap, tap } from 'rxjs'; diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index 898c7f51a8..880753cce5 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -51,7 +51,7 @@ import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { copyOutline, ellipsisVertical } from 'ionicons/icons'; -import { isNumber, keyBy, sortBy, union } from 'lodash'; +import { isNumber, keyBy, sortBy, union } from 'lodash-es'; import ms from 'ms'; import { DeviceDetectorService } from 'ngx-device-detector'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts index dc787ae26a..33b877d42f 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts @@ -27,7 +27,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormControl } from '@angular/forms'; import { Big } from 'big.js'; -import { isFinite, isNumber } from 'lodash'; +import { isFinite, isNumber } from 'lodash-es'; import { DeviceDetectorService } from 'ngx-device-detector'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; diff --git a/apps/client/src/app/services/import-activities.service.ts b/apps/client/src/app/services/import-activities.service.ts index 599c66551a..e302f00f9b 100644 --- a/apps/client/src/app/services/import-activities.service.ts +++ b/apps/client/src/app/services/import-activities.service.ts @@ -16,7 +16,7 @@ import { DataSource, Type as ActivityType } from '@ghostfolio/prisma/enums'; import { HttpClient } from '@angular/common/http'; import { inject, Service } from '@angular/core'; -import { isFinite, isNumber, isString } from 'lodash'; +import { isFinite, isNumber, isString } from 'lodash-es'; import { parse as csvToJson } from 'papaparse'; import { firstValueFrom } from 'rxjs'; import { v4 as uuidv4 } from 'uuid'; diff --git a/eslint.config.cjs b/eslint.config.cjs index ee5e0a557c..282e1b548c 100644 --- a/eslint.config.cjs +++ b/eslint.config.cjs @@ -116,7 +116,24 @@ module.exports = [ 'no-eval': 'error', 'no-fallthrough': 'error', 'no-new-wrappers': 'error', - 'no-restricted-imports': ['error', 'rxjs/Rx'], + 'no-restricted-imports': [ + 'error', + { + paths: [ + 'rxjs/Rx', + { + message: 'Import from lodash-es instead.', + name: 'lodash' + } + ], + patterns: [ + { + group: ['lodash/*'], + message: 'Import from lodash-es instead.' + } + ] + } + ], 'no-undef-init': 'error', 'no-underscore-dangle': 'off', 'no-var': 'error', diff --git a/jest.preset.js b/jest.preset.js index f078ddcec1..3cdca44c04 100644 --- a/jest.preset.js +++ b/jest.preset.js @@ -1,3 +1,6 @@ const nxPreset = require('@nx/jest/preset').default; -module.exports = { ...nxPreset }; +module.exports = { + ...nxPreset, + transformIgnorePatterns: ['node_modules/(?!lodash-es/)'] +}; diff --git a/libs/common/src/lib/calculation-helper.ts b/libs/common/src/lib/calculation-helper.ts index d49663d6cf..2cc1fa2d1c 100644 --- a/libs/common/src/lib/calculation-helper.ts +++ b/libs/common/src/lib/calculation-helper.ts @@ -10,7 +10,7 @@ import { subMilliseconds, subYears } from 'date-fns'; -import { isFinite, isNumber } from 'lodash'; +import { isFinite, isNumber } from 'lodash-es'; import { resetHours } from './helper'; import { DateRange } from './types'; diff --git a/libs/common/src/lib/dtos/create-account.dto.ts b/libs/common/src/lib/dtos/create-account.dto.ts index 92879dbb2c..5c1275db76 100644 --- a/libs/common/src/lib/dtos/create-account.dto.ts +++ b/libs/common/src/lib/dtos/create-account.dto.ts @@ -11,7 +11,7 @@ import { MaxLength, ValidateIf } from 'class-validator'; -import { isString } from 'lodash'; +import { isString } from 'lodash-es'; export class CreateAccountDto { /** diff --git a/libs/common/src/lib/dtos/create-order.dto.ts b/libs/common/src/lib/dtos/create-order.dto.ts index fd062b610b..d473e8e7b6 100644 --- a/libs/common/src/lib/dtos/create-order.dto.ts +++ b/libs/common/src/lib/dtos/create-order.dto.ts @@ -25,7 +25,7 @@ import { Min, Validate } from 'class-validator'; -import { isString } from 'lodash'; +import { isString } from 'lodash-es'; export class CreateOrderDto { @IsOptional() diff --git a/libs/common/src/lib/dtos/update-account.dto.ts b/libs/common/src/lib/dtos/update-account.dto.ts index deec684aae..c5f9f34679 100644 --- a/libs/common/src/lib/dtos/update-account.dto.ts +++ b/libs/common/src/lib/dtos/update-account.dto.ts @@ -11,7 +11,7 @@ import { MaxLength, ValidateIf } from 'class-validator'; -import { isString } from 'lodash'; +import { isString } from 'lodash-es'; export class UpdateAccountDto { /** diff --git a/libs/common/src/lib/dtos/update-order.dto.ts b/libs/common/src/lib/dtos/update-order.dto.ts index 0e381f2069..f7dfb0df53 100644 --- a/libs/common/src/lib/dtos/update-order.dto.ts +++ b/libs/common/src/lib/dtos/update-order.dto.ts @@ -24,7 +24,7 @@ import { Min, Validate } from 'class-validator'; -import { isString } from 'lodash'; +import { isString } from 'lodash-es'; export class UpdateOrderDto { @IsOptional() diff --git a/libs/common/src/lib/helper.ts b/libs/common/src/lib/helper.ts index 69764935d1..e10ca215cc 100644 --- a/libs/common/src/lib/helper.ts +++ b/libs/common/src/lib/helper.ts @@ -42,7 +42,7 @@ import { uk, zhCN } from 'date-fns/locale'; -import { get, isNil, isString } from 'lodash'; +import { get, isNil, isString } from 'lodash-es'; import { DEFAULT_CURRENCY, diff --git a/libs/ui/jest.config.ts b/libs/ui/jest.config.ts index 116fe6d54f..f9b97fe1a4 100644 --- a/libs/ui/jest.config.ts +++ b/libs/ui/jest.config.ts @@ -14,7 +14,7 @@ export default { } ] }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + transformIgnorePatterns: ['node_modules/(?!.*.mjs$|lodash-es/)'], snapshotSerializers: [ 'jest-preset-angular/build/serializers/no-ng-attributes', 'jest-preset-angular/build/serializers/ng-snapshot', diff --git a/libs/ui/src/lib/account-balances/account-balances.component.ts b/libs/ui/src/lib/account-balances/account-balances.component.ts index e27d29516c..04f13ccf10 100644 --- a/libs/ui/src/lib/account-balances/account-balances.component.ts +++ b/libs/ui/src/lib/account-balances/account-balances.component.ts @@ -40,7 +40,7 @@ import { ellipsisHorizontal, trashOutline } from 'ionicons/icons'; -import { get, isNil } from 'lodash'; +import { get, isNil } from 'lodash-es'; import { GfValueComponent } from '../value'; diff --git a/libs/ui/src/lib/activities-filter/activities-filter.component.ts b/libs/ui/src/lib/activities-filter/activities-filter.component.ts index 7a434d94c8..b6af11b0dc 100644 --- a/libs/ui/src/lib/activities-filter/activities-filter.component.ts +++ b/libs/ui/src/lib/activities-filter/activities-filter.component.ts @@ -29,7 +29,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { closeOutline, searchOutline } from 'ionicons/icons'; -import { groupBy } from 'lodash'; +import { groupBy } from 'lodash-es'; import { BehaviorSubject } from 'rxjs'; import { translate } from '../i18n'; diff --git a/libs/ui/src/lib/assistant/assistant.component.ts b/libs/ui/src/lib/assistant/assistant.component.ts index 6babc10398..ef0fb554ce 100644 --- a/libs/ui/src/lib/assistant/assistant.component.ts +++ b/libs/ui/src/lib/assistant/assistant.component.ts @@ -39,7 +39,7 @@ import { closeOutline, searchOutline } from 'ionicons/icons'; -import { isFunction, sample } from 'lodash'; +import { isFunction, sample } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { EMPTY, Observable, merge, of } from 'rxjs'; import { diff --git a/libs/ui/src/lib/benchmark/benchmark.component.ts b/libs/ui/src/lib/benchmark/benchmark.component.ts index 4f76978d45..bee06e3265 100644 --- a/libs/ui/src/lib/benchmark/benchmark.component.ts +++ b/libs/ui/src/lib/benchmark/benchmark.component.ts @@ -33,7 +33,7 @@ import { ActivatedRoute, Router, RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { ellipsisHorizontal, trashOutline } from 'ionicons/icons'; -import { isNumber, round } from 'lodash'; +import { isNumber, round } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { GfEntityLogoComponent } from '../entity-logo/entity-logo.component'; diff --git a/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts b/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts index cfa2ee5cd2..959e934553 100644 --- a/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts +++ b/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts @@ -59,7 +59,7 @@ import { } from 'date-fns'; import { addIcons } from 'ionicons'; import { calendarClearOutline } from 'ionicons/icons'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { debounceTime } from 'rxjs'; diff --git a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts index 17a5a5e612..4f8540974f 100644 --- a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts +++ b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts @@ -29,7 +29,7 @@ import { MatInputModule } from '@angular/material/input'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { calendarClearOutline, refreshOutline } from 'ionicons/icons'; -import { isNil } from 'lodash'; +import { isNil } from 'lodash-es'; import { HistoricalMarketDataEditorDialogParams } from './interfaces/interfaces'; diff --git a/libs/ui/src/lib/notifications/notification.service.ts b/libs/ui/src/lib/notifications/notification.service.ts index 4eb1cbd54d..d1c8459a6c 100644 --- a/libs/ui/src/lib/notifications/notification.service.ts +++ b/libs/ui/src/lib/notifications/notification.service.ts @@ -3,7 +3,7 @@ import { translate } from '@ghostfolio/ui/i18n'; import { inject, Service } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; -import { isFunction } from 'lodash'; +import { isFunction } from 'lodash-es'; import { GfAlertDialogComponent } from './alert-dialog/alert-dialog.component'; import { GfConfirmationDialogComponent } from './confirmation-dialog/confirmation-dialog.component'; diff --git a/libs/ui/src/lib/services/admin.service.ts b/libs/ui/src/lib/services/admin.service.ts index aba02c9b3f..0307909dc1 100644 --- a/libs/ui/src/lib/services/admin.service.ts +++ b/libs/ui/src/lib/services/admin.service.ts @@ -31,7 +31,7 @@ import { GF_ENVIRONMENT } from '@ghostfolio/ui/environment'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { inject, Service } from '@angular/core'; import { JobStatus } from 'bull'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; @Service() export class AdminService { diff --git a/libs/ui/src/lib/services/data.service.ts b/libs/ui/src/lib/services/data.service.ts index 9bbb0bf5fa..8545c36ba4 100644 --- a/libs/ui/src/lib/services/data.service.ts +++ b/libs/ui/src/lib/services/data.service.ts @@ -82,7 +82,7 @@ import { inject, Service } from '@angular/core'; import { SortDirection } from '@angular/material/sort'; import { utc } from '@date-fns/utc'; import { format, parseISO } from 'date-fns'; -import { cloneDeep, groupBy, isNumber } from 'lodash'; +import { cloneDeep, groupBy, isNumber } from 'lodash-es'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; diff --git a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts index 683f7c9252..d56aa177bf 100644 --- a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts +++ b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts @@ -36,7 +36,7 @@ import { } from '@angular/material/form-field'; import { MatInput, MatInputModule } from '@angular/material/input'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; -import { isString } from 'lodash'; +import { isString } from 'lodash-es'; import { tap } from 'rxjs'; import { debounceTime, diff --git a/libs/ui/src/lib/top-holdings/top-holdings.component.ts b/libs/ui/src/lib/top-holdings/top-holdings.component.ts index 03e7f6cc46..1a675a5531 100644 --- a/libs/ui/src/lib/top-holdings/top-holdings.component.ts +++ b/libs/ui/src/lib/top-holdings/top-holdings.component.ts @@ -18,7 +18,7 @@ import { import { MatButtonModule } from '@angular/material/button'; import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; -import { capitalize } from 'lodash'; +import { capitalize } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { GfValueComponent } from '../value/value.component'; diff --git a/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts b/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts index 54c8d7f907..a35d3deef5 100644 --- a/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts +++ b/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -32,7 +32,7 @@ import { Chart, LinearScale, Tooltip } from 'chart.js'; import { TreemapController, TreemapElement } from 'chartjs-chart-treemap'; import { isUUID } from 'class-validator'; import { differenceInDays, max } from 'date-fns'; -import { orderBy, round } from 'lodash'; +import { orderBy, round } from 'lodash-es'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import OpenColor from 'open-color'; diff --git a/libs/ui/src/lib/value/value.component.ts b/libs/ui/src/lib/value/value.component.ts index c2c7d4621d..4101b4066f 100644 --- a/libs/ui/src/lib/value/value.component.ts +++ b/libs/ui/src/lib/value/value.component.ts @@ -21,7 +21,7 @@ import { MatSnackBar } from '@angular/material/snack-bar'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { checkmarkOutline, copyOutline } from 'ionicons/icons'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; import ms from 'ms'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; diff --git a/package-lock.json b/package-lock.json index 3f8ee0f880..c3ee51dc53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -83,7 +83,7 @@ "ionicons": "8.0.13", "jsonpath": "1.3.0", "katex": "0.16.47", - "lodash": "4.18.1", + "lodash-es": "4.18.1", "marked": "18.0.12", "marked-katex-extension": "5.1.12", "ms": "3.0.0-canary.1", @@ -147,7 +147,7 @@ "@types/google-spreadsheet": "3.1.5", "@types/jest": "30.0.0", "@types/jsonpath": "0.2.4", - "@types/lodash": "4.17.25", + "@types/lodash-es": "4.17.12", "@types/node": "22.20.1", "@types/papaparse": "5.5.2", "@types/passport-google-oauth20": "2.0.17", @@ -15221,6 +15221,16 @@ "devOptional": true, "license": "MIT" }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/luxon": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.7.1.tgz", @@ -27042,7 +27052,6 @@ "version": "4.18.1", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", - "dev": true, "license": "MIT" }, "node_modules/lodash.debounce": { diff --git a/package.json b/package.json index a3f94b74b6..ca4f3ebcff 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "ionicons": "8.0.13", "jsonpath": "1.3.0", "katex": "0.16.47", - "lodash": "4.18.1", + "lodash-es": "4.18.1", "marked": "18.0.12", "marked-katex-extension": "5.1.12", "ms": "3.0.0-canary.1", @@ -191,7 +191,7 @@ "@types/google-spreadsheet": "3.1.5", "@types/jest": "30.0.0", "@types/jsonpath": "0.2.4", - "@types/lodash": "4.17.25", + "@types/lodash-es": "4.17.12", "@types/node": "22.20.1", "@types/papaparse": "5.5.2", "@types/passport-google-oauth20": "2.0.17",