Auto commit for release 'develop' on 2024-08-05

This commit is contained in:
github-actions
2024-08-05 05:06:53 +02:00
parent d2e9b64bf5
commit ed265f68ba
32 changed files with 574 additions and 564 deletions

View File

@@ -406,16 +406,16 @@
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.60.0", "version": "v3.61.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "e595e4e070d17c5d42ed8c4206f630fcc5f401a4" "reference": "94a87189f55814e6cabca2d9a33b06de384a2ab8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/e595e4e070d17c5d42ed8c4206f630fcc5f401a4", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/94a87189f55814e6cabca2d9a33b06de384a2ab8",
"reference": "e595e4e070d17c5d42ed8c4206f630fcc5f401a4", "reference": "94a87189f55814e6cabca2d9a33b06de384a2ab8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -497,7 +497,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.60.0" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.61.1"
}, },
"funding": [ "funding": [
{ {
@@ -505,7 +505,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-07-25T09:26:51+00:00" "time": "2024-07-31T14:33:15+00:00"
}, },
{ {
"name": "psr/container", "name": "psr/container",

View File

@@ -4,6 +4,7 @@ Over time, many people have contributed to Firefly III. Their efforts are not al
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution. Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
## 2024 ## 2024
- withbest
- Steve Wasiura - Steve Wasiura
- imlonghao - imlonghao
- Rahman Yusuf - Rahman Yusuf

View File

@@ -170,7 +170,6 @@ class UpdateController extends Controller
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
// safety catch on currency disablement. // safety catch on currency disablement.
$set = $this->repository->get(); $set = $this->repository->get();
if (array_key_exists('enabled', $data) && false === $data['enabled'] && 1 === count($set) && $set->first()->id === $currency->id) { if (array_key_exists('enabled', $data) && false === $data['enabled'] && 1 === count($set) && $set->first()->id === $currency->id) {

View File

@@ -102,6 +102,7 @@ class PreferencesController extends Controller
* TODO This endpoint is not documented. * TODO This endpoint is not documented.
* *
* Return a single preference by name. * Return a single preference by name.
*
* @param Collection<int, Preference> $collection * @param Collection<int, Preference> $collection
*/ */
public function showList(Collection $collection): JsonResponse public function showList(Collection $collection): JsonResponse

View File

@@ -46,7 +46,7 @@ class AccountController extends Controller
use Actions\Destroy; use Actions\Destroy;
use Actions\DetachRelationship; use Actions\DetachRelationship;
use Actions\FetchMany; use Actions\FetchMany;
// use Actions\FetchOne; // use Actions\FetchOne;
use Actions\FetchRelated; use Actions\FetchRelated;
use Actions\FetchRelationship; use Actions\FetchRelationship;
@@ -66,7 +66,8 @@ class AccountController extends Controller
->repository() ->repository()
->queryAll() ->queryAll()
->withRequest($request) ->withRequest($request)
->get(); ->get()
;
// do something custom... // do something custom...

View File

@@ -43,8 +43,8 @@ class OtherCurrenciesCorrections extends Command
use ShowsFriendlyMessages; use ShowsFriendlyMessages;
public const string CONFIG_NAME = '480_other_currencies'; public const string CONFIG_NAME = '480_other_currencies';
protected $description = 'Update all journal currency information.'; protected $description = 'Update all journal currency information.';
protected $signature = 'firefly-iii:other-currencies {--F|force : Force the execution of this command.}'; protected $signature = 'firefly-iii:other-currencies {--F|force : Force the execution of this command.}';
private array $accountCurrencies; private array $accountCurrencies;
private AccountRepositoryInterface $accountRepos; private AccountRepositoryInterface $accountRepos;
private JournalCLIRepositoryInterface $cliRepos; private JournalCLIRepositoryInterface $cliRepos;
@@ -220,14 +220,14 @@ class OtherCurrenciesCorrections extends Command
private function getCurrency(Account $account): ?TransactionCurrency private function getCurrency(Account $account): ?TransactionCurrency
{ {
$accountId = $account->id; $accountId = $account->id;
if (array_key_exists($accountId, $this->accountCurrencies) && 0 === $this->accountCurrencies[$accountId]) { if (array_key_exists($accountId, $this->accountCurrencies) && 0 === $this->accountCurrencies[$accountId]) {
return null; return null;
} }
if (array_key_exists($accountId, $this->accountCurrencies) && $this->accountCurrencies[$accountId] instanceof TransactionCurrency) { if (array_key_exists($accountId, $this->accountCurrencies) && $this->accountCurrencies[$accountId] instanceof TransactionCurrency) {
return $this->accountCurrencies[$accountId]; return $this->accountCurrencies[$accountId];
} }
$currency = $this->accountRepos->getAccountCurrency($account); $currency = $this->accountRepos->getAccountCurrency($account);
if (null === $currency) { if (null === $currency) {
$this->accountCurrencies[$accountId] = 0; $this->accountCurrencies[$accountId] = 0;
@@ -249,6 +249,7 @@ class OtherCurrenciesCorrections extends Command
if (false === $value || null === $value) { if (false === $value || null === $value) {
return false; return false;
} }
return '1' === $value; return '1' === $value;
} }
} }

View File

@@ -29,28 +29,28 @@ class AccountCollectionQuery extends ResourceQuery
'array', 'array',
JsonApiRule::fieldSets(), JsonApiRule::fieldSets(),
], ],
'userGroupId' => [ 'userGroupId' => [
'nullable', 'nullable',
'integer', 'integer',
new IsAllowedGroupAction(Account::class, request()->method()), new IsAllowedGroupAction(Account::class, request()->method()),
], ],
'startPeriod' => [ 'startPeriod' => [
'nullable', 'nullable',
'date', 'date',
new IsDateOrTime(), new IsDateOrTime(),
new isValidDateRange(), new IsValidDateRange(),
], ],
'endPeriod' => [ 'endPeriod' => [
'nullable', 'nullable',
'date', 'date',
new IsDateOrTime(), new IsDateOrTime(),
new isValidDateRange(), new IsValidDateRange(),
], ],
'filter' => [ 'filter' => [
'nullable', 'nullable',
'array', 'array',
JsonApiRule::filter($validFilters), JsonApiRule::filter($validFilters),
new IsValidAccountType() new IsValidAccountType(),
], ],
'include' => [ 'include' => [
'nullable', 'nullable',

View File

@@ -29,10 +29,8 @@ use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use LaravelJsonApi\Contracts\Store\CreatesResources; use LaravelJsonApi\Contracts\Store\CreatesResources;
use LaravelJsonApi\Contracts\Store\QueriesAll; use LaravelJsonApi\Contracts\Store\QueriesAll;
use LaravelJsonApi\Contracts\Store\QueryOneBuilder;
use LaravelJsonApi\NonEloquent\AbstractRepository; use LaravelJsonApi\NonEloquent\AbstractRepository;
use LaravelJsonApi\NonEloquent\Capabilities\CrudRelations; use LaravelJsonApi\NonEloquent\Capabilities\CrudRelations;
use LaravelJsonApi\NonEloquent\Capabilities\CrudResource;
use LaravelJsonApi\NonEloquent\Concerns\HasCrudCapability; use LaravelJsonApi\NonEloquent\Concerns\HasCrudCapability;
use LaravelJsonApi\NonEloquent\Concerns\HasRelationsCapability; use LaravelJsonApi\NonEloquent\Concerns\HasRelationsCapability;
@@ -52,26 +50,25 @@ class AccountRepository extends AbstractRepository implements QueriesAll, Create
use HasRelationsCapability; use HasRelationsCapability;
use UsergroupAware; use UsergroupAware;
/** /**
* SiteRepository constructor. * SiteRepository constructor.
*/ */
public function __construct() { public function __construct()
{
Log::debug(__METHOD__); Log::debug(__METHOD__);
} }
public function exists(string $resourceId): bool public function exists(string $resourceId): bool
{ {
$result = null !== Account::find((int) $resourceId); $result = null !== Account::find((int) $resourceId);
Log::debug(sprintf('%s: %s',__METHOD__, var_export($result, true))); Log::debug(sprintf('%s: %s', __METHOD__, var_export($result, true)));
return $result; return $result;
} }
public function find(string $resourceId): ?object public function find(string $resourceId): ?object
{ {
die(__METHOD__); exit(__METHOD__);
Log::debug(__METHOD__); Log::debug(__METHOD__);
// throw new \RuntimeException('trace me'); // throw new \RuntimeException('trace me');
$account = Account::find((int) $resourceId); $account = Account::find((int) $resourceId);
@@ -98,12 +95,14 @@ class AccountRepository extends AbstractRepository implements QueriesAll, Create
protected function crud(): Capabilities\CrudAccount protected function crud(): Capabilities\CrudAccount
{ {
Log::debug(__METHOD__); Log::debug(__METHOD__);
return Capabilities\CrudAccount::make(); return Capabilities\CrudAccount::make();
} }
protected function relations(): CrudRelations protected function relations(): CrudRelations
{ {
Log::debug(__METHOD__); Log::debug(__METHOD__);
return Capabilities\CrudAccountRelations::make(); return Capabilities\CrudAccountRelations::make();
} }
} }

View File

@@ -1,28 +1,27 @@
<?php <?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V2\Accounts; namespace FireflyIII\JsonApi\V2\Accounts;
use FireflyIII\Rules\BelongsUser; use FireflyIII\Rules\BelongsUser;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;
use LaravelJsonApi\Laravel\Http\Requests\ResourceRequest; use LaravelJsonApi\Laravel\Http\Requests\ResourceRequest;
use LaravelJsonApi\Validation\Rule as JsonApiRule;
class AccountRequest extends ResourceRequest class AccountRequest extends ResourceRequest
{ {
/** /**
* Get the validation rules for the resource. * Get the validation rules for the resource.
*
* @return array
*/ */
public function rules(): array public function rules(): array
{ {
Log::debug(__METHOD__); Log::debug(__METHOD__);
die('am i used');
exit('am i used');
return [ return [
'type' => [ 'type' => [
new BelongsUser() new BelongsUser(),
], ],
'name' => [ 'name' => [
'nullable', 'nullable',
@@ -31,5 +30,4 @@ class AccountRequest extends ResourceRequest
], ],
]; ];
} }
} }

View File

@@ -29,7 +29,7 @@ class AccountResource extends JsonApiResource
*/ */
public function attributes($request): iterable public function attributes($request): iterable
{ {
//Log::debug(__METHOD__); // Log::debug(__METHOD__);
return [ return [
'created_at' => $this->resource->created_at, 'created_at' => $this->resource->created_at,
@@ -63,7 +63,6 @@ class AccountResource extends JsonApiResource
// other things // other things
'last_activity' => $this->resource->last_activity, 'last_activity' => $this->resource->last_activity,
// object group // object group
'object_group_id' => $this->resource->object_group_id, 'object_group_id' => $this->resource->object_group_id,
'object_group_title' => $this->resource->object_group_title, 'object_group_title' => $this->resource->object_group_title,

View File

@@ -28,7 +28,7 @@ class AccountSchema extends Schema
*/ */
public function fields(): array public function fields(): array
{ {
Log::debug(__METHOD__); Log::debug(__METHOD__);
return [ return [
ID::make(), ID::make(),
@@ -87,6 +87,7 @@ class AccountSchema extends Schema
foreach ($config as $entry) { foreach ($config as $entry) {
$array[] = Filter::make($entry); $array[] = Filter::make($entry);
} }
return $array; return $array;
} }
@@ -94,18 +95,18 @@ class AccountSchema extends Schema
{ {
Log::debug(__METHOD__); Log::debug(__METHOD__);
$this->setUserGroup($this->server->getUsergroup()); $this->setUserGroup($this->server->getUsergroup());
return AccountRepository::make() return AccountRepository::make()
->withServer($this->server) ->withServer($this->server)
->withSchema($this) ->withSchema($this)
->withUserGroup($this->userGroup); ->withUserGroup($this->userGroup)
;
} }
/**
* @inheritDoc
*/
public function pagination(): EnumerablePagination public function pagination(): EnumerablePagination
{ {
Log::debug(__METHOD__); Log::debug(__METHOD__);
return EnumerablePagination::make(); return EnumerablePagination::make();
} }
} }

View File

@@ -41,16 +41,16 @@ use LaravelJsonApi\NonEloquent\Capabilities\QueryAll;
class AccountQuery extends QueryAll implements HasPagination class AccountQuery extends QueryAll implements HasPagination
{ {
use AccountFilter;
use CollectsCustomParameters;
use ExpandsQuery; use ExpandsQuery;
use FiltersPagination; use FiltersPagination;
use SortsCollection; use SortsCollection;
use SortsQueryResults;
use UsergroupAware; use UsergroupAware;
use ValidateSortParameters; use ValidateSortParameters;
use CollectsCustomParameters;
use AccountFilter;
use SortsQueryResults;
//use PaginatesEnumerables; // use PaginatesEnumerables;
#[\Override] #[\Override]
/** /**
@@ -62,49 +62,46 @@ class AccountQuery extends QueryAll implements HasPagination
{ {
Log::debug(__METHOD__); Log::debug(__METHOD__);
// collect sort options // collect sort options
$sort = $this->queryParameters->sortFields(); $sort = $this->queryParameters->sortFields();
// collect pagination based on the page // collect pagination based on the page
$pagination = $this->filtersPagination($this->queryParameters->page()); $pagination = $this->filtersPagination($this->queryParameters->page());
// check if we need all accounts, regardless of pagination // check if we need all accounts, regardless of pagination
// This is necessary when the user wants to sort on specific params. // This is necessary when the user wants to sort on specific params.
$needsAll = $this->needsFullDataset(Account::class, $sort); $needsAll = $this->needsFullDataset(Account::class, $sort);
// params that were not recognised, may be my own custom stuff. // params that were not recognised, may be my own custom stuff.
$otherParams = $this->getOtherParams($this->queryParameters->unrecognisedParameters()); $otherParams = $this->getOtherParams($this->queryParameters->unrecognisedParameters());
// start the query // start the query
$query = $this->userGroup->accounts(); $query = $this->userGroup->accounts();
// add sort and filter parameters to the query. // add sort and filter parameters to the query.
$query = $this->addSortParams(Account::class, $query, $sort); $query = $this->addSortParams(Account::class, $query, $sort);
$query = $this->addFilterParams(Account::class, $query, $this->queryParameters->filter()); $query = $this->addFilterParams(Account::class, $query, $this->queryParameters->filter());
// collect the result. // collect the result.
$collection = $query->get(['accounts.*']); $collection = $query->get(['accounts.*']);
// sort the data after the query, and return it right away. // sort the data after the query, and return it right away.
$collection = $this->sortCollection(Account::class, $collection, $sort); $collection = $this->sortCollection(Account::class, $collection, $sort);
// if the entire collection needs to be enriched and sorted, do so now: // if the entire collection needs to be enriched and sorted, do so now:
$totalCount = $collection->count(); $totalCount = $collection->count();
Log::debug(sprintf('Total is %d', $totalCount)); Log::debug(sprintf('Total is %d', $totalCount));
if ($needsAll) { if ($needsAll) {
Log::debug('Needs the entire collection'); Log::debug('Needs the entire collection');
// enrich the entire collection // enrich the entire collection
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setStart($otherParams['start'] ?? null); $enrichment->setStart($otherParams['start'] ?? null);
$enrichment->setEnd($otherParams['end'] ?? null); $enrichment->setEnd($otherParams['end'] ?? null);
$collection = $enrichment->enrich($collection); $collection = $enrichment->enrich($collection);
// TODO sort the set based on post-query sort options: // TODO sort the set based on post-query sort options:
$collection = $this->postQuerySort(Account::class, $collection, $sort); $collection = $this->postQuerySort(Account::class, $collection, $sort);
// take the current page from the enriched set. // take the current page from the enriched set.
$currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']); $currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
} }
if (!$needsAll) { if (!$needsAll) {
Log::debug('Needs only partial collection'); Log::debug('Needs only partial collection');
@@ -112,38 +109,33 @@ class AccountQuery extends QueryAll implements HasPagination
$currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']); $currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
// enrich only the current page. // enrich only the current page.
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setStart($otherParams['start'] ?? null); $enrichment->setStart($otherParams['start'] ?? null);
$enrichment->setEnd($otherParams['end'] ?? null); $enrichment->setEnd($otherParams['end'] ?? null);
$currentPage = $enrichment->enrich($currentPage); $currentPage = $enrichment->enrich($currentPage);
} }
// get current page? // get current page?
Log::debug(sprintf('Skip %d, take %d', ($pagination['number'] - 1) * $pagination['size'], $pagination['size'])); Log::debug(sprintf('Skip %d, take %d', ($pagination['number'] - 1) * $pagination['size'], $pagination['size']));
//$currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']); // $currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
Log::debug(sprintf('New collection size: %d', $currentPage->count())); Log::debug(sprintf('New collection size: %d', $currentPage->count()));
// TODO add filters after the query, if there are filters that cannot be applied to the database // TODO add filters after the query, if there are filters that cannot be applied to the database
// TODO same for sort things. // TODO same for sort things.
return new LengthAwarePaginator($currentPage, $totalCount, $pagination['size'], $pagination['number']); return new LengthAwarePaginator($currentPage, $totalCount, $pagination['size'], $pagination['number']);
} }
/** #[\Override]
* @inheritDoc public function paginate(array $page): Page
*/
#[\Override] public function paginate(array $page): Page
{ {
die('here weare'); exit('here weare');
// TODO: Implement paginate() method. // TODO: Implement paginate() method.
} }
/** #[\Override]
* @inheritDoc public function getOrPaginate(?array $page): iterable
*/
#[\Override] public function getOrPaginate(?array $page): iterable
{ {
die('here weare'); exit('here weare');
// TODO: Implement getOrPaginate() method. // TODO: Implement getOrPaginate() method.
} }
} }

View File

@@ -42,17 +42,17 @@ class CrudAccount extends CrudResource
Log::debug(__METHOD__); Log::debug(__METHOD__);
// enrich the collected data // enrich the collected data
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
// set start and date, if present. // set start and date, if present.
$enrichment->setStart($otherParams['start'] ?? null); $enrichment->setStart($otherParams['start'] ?? null);
$enrichment->setEnd($otherParams['end'] ?? null); $enrichment->setEnd($otherParams['end'] ?? null);
return $enrichment->enrichSingle($account); return $enrichment->enrichSingle($account);
} }
public function create(array $validatedData): Account { public function create(array $validatedData): Account
die('here we are'); {
exit('here we are');
} }
} }

View File

@@ -45,6 +45,7 @@ class AccountPolicy
public function viewAny(): bool public function viewAny(): bool
{ {
Log::debug(__METHOD__); Log::debug(__METHOD__);
return auth()->check(); return auth()->check();
} }

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Rules\Account; namespace FireflyIII\Rules\Account;
use Closure;
use FireflyIII\Support\Http\Api\AccountFilter; use FireflyIII\Support\Http\Api\AccountFilter;
use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Contracts\Validation\ValidationRule;
@@ -31,12 +30,9 @@ class IsValidAccountType implements ValidationRule
{ {
use AccountFilter; use AccountFilter;
/** #[\Override]
* @inheritDoc public function validate(string $attribute, mixed $value, \Closure $fail): void
*/
#[\Override] public function validate(string $attribute, mixed $value, Closure $fail): void
{ {
// only check the type. // only check the type.
if (array_key_exists('type', $value)) { if (array_key_exists('type', $value)) {
$value = $value['type']; $value = $value['type'];
@@ -44,13 +40,13 @@ class IsValidAccountType implements ValidationRule
$value = [$value]; $value = [$value];
} }
$filtered = []; $filtered = [];
$keys = array_keys($this->types); $keys = array_keys($this->types);
/** @var mixed $entry */ /** @var mixed $entry */
foreach ($value as $entry) { foreach ($value as $entry) {
$entry = (string) $entry; $entry = (string) $entry;
if (!in_array($entry, $keys)) { if (!in_array($entry, $keys, true)) {
$fail('something'); $fail('something');
} }
} }

View File

@@ -35,17 +35,18 @@ class IsValidDateRange implements ValidationRule
*/ */
public function validate(string $attribute, mixed $value, \Closure $fail): void public function validate(string $attribute, mixed $value, \Closure $fail): void
{ {
$value = (string) $value; $value = (string) $value;
if ('' === $value) { if ('' === $value) {
$fail('validation.date_or_time')->translate(); $fail('validation.date_or_time')->translate();
return; return;
} }
$other = 'startPeriod'; $other = 'startPeriod';
if ('startPeriod' === $attribute) { if ('startPeriod' === $attribute) {
$other = 'endPeriod'; $other = 'endPeriod';
} }
$otherValue = request()->get($other); $otherValue = request()->get($other);
// parse date, twice. // parse date, twice.
try { try {
$left = Carbon::parse($value); $left = Carbon::parse($value);
@@ -68,6 +69,7 @@ class IsValidDateRange implements ValidationRule
if ($left->gt($right)) { if ($left->gt($right)) {
$fail('validation.date_after')->translate(); $fail('validation.date_after')->translate();
} }
return; return;
} }
// end must be after start // end must be after start
@@ -76,4 +78,3 @@ class IsValidDateRange implements ValidationRule
} }
} }
} }

View File

@@ -45,8 +45,10 @@ class Amount
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured); return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
} }
public function formatByCurrencyId(int $currencyId, string $amount, ?bool $coloured = null): string { public function formatByCurrencyId(int $currencyId, string $amount, ?bool $coloured = null): string
{
$format = TransactionCurrency::find($currencyId); $format = TransactionCurrency::find($currencyId);
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured); return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
} }

View File

@@ -31,14 +31,8 @@ use Illuminate\Support\Facades\Log;
class Balance class Balance
{ {
/** /**
* Returns the accounts balances as an array, on the account ID. * Returns the accounts balances as an array, on the account ID.
*
* @param Collection $accounts
* @param Carbon $date
*
* @return array
*/ */
public function getAccountBalances(Collection $accounts, Carbon $date): array public function getAccountBalances(Collection $accounts, Carbon $date): array
{ {
@@ -53,19 +47,19 @@ class Balance
return $cache->get(); return $cache->get();
} }
$query = Transaction:: $query = Transaction::whereIn('transactions.account_id', $accounts->pluck('id')->toArray())
whereIn('transactions.account_id', $accounts->pluck('id')->toArray()) ->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->orderBy('transaction_journals.date', 'desc')
->orderBy('transaction_journals.date', 'desc') ->orderBy('transaction_journals.order', 'asc')
->orderBy('transaction_journals.order', 'asc') ->orderBy('transaction_journals.description', 'desc')
->orderBy('transaction_journals.description', 'desc') ->orderBy('transactions.amount', 'desc')
->orderBy('transactions.amount', 'desc') ->where('transaction_journals.date', '<=', $date)
->where('transaction_journals.date', '<=', $date); ;
$result = $query->get(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.balance_after']); $result = $query->get(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.balance_after']);
foreach ($result as $entry) { foreach ($result as $entry) {
$accountId = (int) $entry->account_id; $accountId = (int) $entry->account_id;
$currencyId = (int) $entry->transaction_currency_id; $currencyId = (int) $entry->transaction_currency_id;
$currencies[$currencyId] ??= TransactionCurrency::find($currencyId); $currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
$return[$accountId] ??= []; $return[$accountId] ??= [];
if (array_key_exists($currencyId, $return[$accountId])) { if (array_key_exists($currencyId, $return[$accountId])) {
@@ -73,7 +67,7 @@ class Balance
} }
$return[$accountId][$currencyId] = ['currency' => $currencies[$currencyId], 'balance' => $entry->balance_after, 'date' => clone $date]; $return[$accountId][$currencyId] = ['currency' => $currencies[$currencyId], 'balance' => $entry->balance_after, 'date' => clone $date];
} }
return $return;
return $return;
} }
} }

View File

@@ -81,6 +81,7 @@ trait AccountFilter
'creditcard' => [AccountType::CREDITCARD], 'creditcard' => [AccountType::CREDITCARD],
'cc' => [AccountType::CREDITCARD], 'cc' => [AccountType::CREDITCARD],
]; ];
/** /**
* All the available types. * All the available types.
*/ */

View File

@@ -44,7 +44,6 @@ class ExchangeRateConverter
private array $prepared = []; private array $prepared = [];
private int $queryCount = 0; private int $queryCount = 0;
public function enabled(): bool public function enabled(): bool
{ {
return false !== config('cer.enabled'); return false !== config('cer.enabled');
@@ -85,8 +84,8 @@ class ExchangeRateConverter
*/ */
private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
{ {
$key = $this->getCacheKey($from, $to, $date); $key = $this->getCacheKey($from, $to, $date);
$res = Cache::get($key, null); $res = Cache::get($key, null);
// find in cache // find in cache
if (null !== $res) { if (null !== $res) {
@@ -96,7 +95,7 @@ class ExchangeRateConverter
} }
// find in database // find in database
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d')); $rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
if (null !== $rate) { if (null !== $rate) {
Cache::forever($key, $rate); Cache::forever($key, $rate);
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d'))); Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
@@ -105,7 +104,7 @@ class ExchangeRateConverter
} }
// find reverse in database // find reverse in database
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d')); $rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
if (null !== $rate) { if (null !== $rate) {
$rate = bcdiv('1', $rate); $rate = bcdiv('1', $rate);
Cache::forever($key, $rate); Cache::forever($key, $rate);
@@ -138,7 +137,7 @@ class ExchangeRateConverter
if ($from === $to) { if ($from === $to) {
return '1'; return '1';
} }
$key = sprintf('cer-%d-%d-%s', $from, $to, $date); $key = sprintf('cer-%d-%d-%s', $from, $to, $date);
// perhaps the rate has been cached during this particular run // perhaps the rate has been cached during this particular run
$preparedRate = $this->prepared[$date][$from][$to] ?? null; $preparedRate = $this->prepared[$date][$from][$to] ?? null;
@@ -148,7 +147,7 @@ class ExchangeRateConverter
return $preparedRate; return $preparedRate;
} }
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($key); $cache->addProperty($key);
if ($cache->has()) { if ($cache->has()) {
$rate = $cache->get(); $rate = $cache->get();
@@ -161,15 +160,16 @@ class ExchangeRateConverter
} }
/** @var null|CurrencyExchangeRate $result */ /** @var null|CurrencyExchangeRate $result */
$result = auth()->user() $result = auth()->user()
->currencyExchangeRates() ->currencyExchangeRates()
->where('from_currency_id', $from) ->where('from_currency_id', $from)
->where('to_currency_id', $to) ->where('to_currency_id', $to)
->where('date', '<=', $date) ->where('date', '<=', $date)
->orderBy('date', 'DESC') ->orderBy('date', 'DESC')
->first(); ->first()
;
++$this->queryCount; ++$this->queryCount;
$rate = (string) $result?->rate; $rate = (string) $result?->rate;
if ('' === $rate) { if ('' === $rate) {
app('log')->debug(sprintf('ExchangeRateConverter: Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date)); app('log')->debug(sprintf('ExchangeRateConverter: Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date));
@@ -209,13 +209,13 @@ class ExchangeRateConverter
if ($euroId === $currency->id) { if ($euroId === $currency->id) {
return '1'; return '1';
} }
$rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d')); $rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d'));
if (null !== $rate) { if (null !== $rate) {
// app('log')->debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate)); // app('log')->debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate));
return $rate; return $rate;
} }
$rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d')); $rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d'));
if (null !== $rate) { if (null !== $rate) {
return bcdiv('1', $rate); return bcdiv('1', $rate);
// app('log')->debug(sprintf('Inverted rate for %s to EUR is %s.', $currency->code, $rate)); // app('log')->debug(sprintf('Inverted rate for %s to EUR is %s.', $currency->code, $rate));
@@ -244,7 +244,7 @@ class ExchangeRateConverter
if ($cache->has()) { if ($cache->has()) {
return (int) $cache->get(); return (int) $cache->get();
} }
$euro = TransactionCurrency::whereCode('EUR')->first(); $euro = TransactionCurrency::whereCode('EUR')->first();
++$this->queryCount; ++$this->queryCount;
if (null === $euro) { if (null === $euro) {
throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.'); throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.');
@@ -266,13 +266,14 @@ class ExchangeRateConverter
$start->startOfDay(); $start->startOfDay();
$end->endOfDay(); $end->endOfDay();
Log::debug(sprintf('Preparing for %s to %s between %s and %s', $from->code, $to->code, $start->format('Y-m-d'), $end->format('Y-m-d'))); Log::debug(sprintf('Preparing for %s to %s between %s and %s', $from->code, $to->code, $start->format('Y-m-d'), $end->format('Y-m-d')));
$set = auth()->user() $set = auth()->user()
->currencyExchangeRates() ->currencyExchangeRates()
->where('from_currency_id', $from->id) ->where('from_currency_id', $from->id)
->where('to_currency_id', $to->id) ->where('to_currency_id', $to->id)
->where('date', '<=', $end->format('Y-m-d')) ->where('date', '<=', $end->format('Y-m-d'))
->where('date', '>=', $start->format('Y-m-d')) ->where('date', '>=', $start->format('Y-m-d'))
->orderBy('date', 'DESC')->get(); ->orderBy('date', 'DESC')->get()
;
++$this->queryCount; ++$this->queryCount;
if (0 === $set->count()) { if (0 === $set->count()) {
Log::debug('No prepared rates found in this period, use the fallback'); Log::debug('No prepared rates found in this period, use the fallback');
@@ -286,10 +287,10 @@ class ExchangeRateConverter
$this->isPrepared = true; $this->isPrepared = true;
// so there is a fallback just in case. Now loop the set of rates we DO have. // so there is a fallback just in case. Now loop the set of rates we DO have.
$temp = []; $temp = [];
$count = 0; $count = 0;
foreach ($set as $rate) { foreach ($set as $rate) {
$date = $rate->date->format('Y-m-d'); $date = $rate->date->format('Y-m-d');
$temp[$date] ??= [ $temp[$date] ??= [
$from->id => [ $from->id => [
$to->id => $rate->rate, $to->id => $rate->rate,
@@ -298,11 +299,11 @@ class ExchangeRateConverter
++$count; ++$count;
} }
Log::debug(sprintf('Found %d rates in this period.', $count)); Log::debug(sprintf('Found %d rates in this period.', $count));
$currentStart = clone $start; $currentStart = clone $start;
while ($currentStart->lte($end)) { while ($currentStart->lte($end)) {
$currentDate = $currentStart->format('Y-m-d'); $currentDate = $currentStart->format('Y-m-d');
$this->prepared[$currentDate] ??= []; $this->prepared[$currentDate] ??= [];
$fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0'; $fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0';
if (0 === count($this->prepared[$currentDate]) && 0 !== bccomp('0', $fallback)) { if (0 === count($this->prepared[$currentDate]) && 0 !== bccomp('0', $fallback)) {
// fill from temp or fallback or from temp (see before) // fill from temp or fallback or from temp (see before)
$this->prepared[$currentDate][$from->id][$to->id] = $fallback; $this->prepared[$currentDate][$from->id][$to->id] = $fallback;

View File

@@ -441,7 +441,7 @@ trait PeriodOverview
$cache->addProperty('tag-period-entries'); $cache->addProperty('tag-period-entries');
$cache->addProperty($tag->id); $cache->addProperty($tag->id);
if ($cache->has()) { if ($cache->has()) {
return $cache->get(); return $cache->get();
} }
/** @var array $dates */ /** @var array $dates */

View File

@@ -27,7 +27,6 @@ use Carbon\Carbon;
trait CollectsCustomParameters trait CollectsCustomParameters
{ {
protected function getOtherParams(array $params): array protected function getOtherParams(array $params): array
{ {
$return = []; $return = [];
@@ -37,7 +36,7 @@ trait CollectsCustomParameters
if (array_key_exists('endPeriod', $params)) { if (array_key_exists('endPeriod', $params)) {
$return['end'] = Carbon::parse($params['endPeriod']); $return['end'] = Carbon::parse($params['endPeriod']);
} }
if(array_key_exists('currentMoment', $params)) { if (array_key_exists('currentMoment', $params)) {
$return['today'] = Carbon::parse($params['currentMoment']); $return['today'] = Carbon::parse($params['currentMoment']);
} }

View File

@@ -117,8 +117,8 @@ class AccountEnrichment implements EnrichmentInterface
$default = $this->default; $default = $this->default;
// get start and end, so the balance difference can be generated. // get start and end, so the balance difference can be generated.
$start = null; $start = null;
$end = null; $end = null;
if (null !== $this->start) { if (null !== $this->start) {
$start = Balance::getAccountBalances($this->collection, $this->start); $start = Balance::getAccountBalances($this->collection, $this->start);
} }
@@ -140,7 +140,7 @@ class AccountEnrichment implements EnrichmentInterface
'balance_difference' => null, 'balance_difference' => null,
]; ];
if (array_key_exists($account->id, $balances)) { if (array_key_exists($account->id, $balances)) {
$set = []; $set = [];
foreach ($balances[$account->id] as $currencyId => $entry) { foreach ($balances[$account->id] as $currencyId => $entry) {
$left = $start[$account->id][$currencyId]['balance'] ?? null; $left = $start[$account->id][$currencyId]['balance'] ?? null;
$right = $end[$account->id][$currencyId]['balance'] ?? null; $right = $end[$account->id][$currencyId]['balance'] ?? null;
@@ -176,7 +176,6 @@ class AccountEnrichment implements EnrichmentInterface
} }
} }
return $account; return $account;
}); });
} }
@@ -205,7 +204,7 @@ class AccountEnrichment implements EnrichmentInterface
$metaFields = $this->repository->getMetaValues($this->collection, ['is_multi_currency', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']); $metaFields = $this->repository->getMetaValues($this->collection, ['is_multi_currency', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']);
$currencyIds = $metaFields->where('name', 'currency_id')->pluck('data')->toArray(); $currencyIds = $metaFields->where('name', 'currency_id')->pluck('data')->toArray();
$currencies = []; $currencies = [];
foreach ($this->currencyRepository->getByIds($currencyIds) as $currency) { foreach ($this->currencyRepository->getByIds($currencyIds) as $currency) {
$id = $currency->id; $id = $currency->id;
$currencies[$id] = $currency; $currencies[$id] = $currency;
@@ -250,31 +249,33 @@ class AccountEnrichment implements EnrichmentInterface
private function getObjectGroups(): void private function getObjectGroups(): void
{ {
$set = \DB::table('object_groupables') $set = \DB::table('object_groupables')
->where('object_groupable_type', Account::class) ->where('object_groupable_type', Account::class)
->whereIn('object_groupable_id', $this->collection->pluck('id')->toArray()) ->whereIn('object_groupable_id', $this->collection->pluck('id')->toArray())
->distinct() ->distinct()
->get(['object_groupables.object_groupable_id', 'object_groupables.object_group_id']); ->get(['object_groupables.object_groupable_id', 'object_groupables.object_group_id'])
;
// get the groups: // get the groups:
$groupIds = $set->pluck('object_group_id')->toArray(); $groupIds = $set->pluck('object_group_id')->toArray();
$groups = ObjectGroup::whereIn('id', $groupIds)->get(); $groups = ObjectGroup::whereIn('id', $groupIds)->get();
/** @var ObjectGroup $group */ /** @var ObjectGroup $group */
foreach ($groups as $group) { foreach ($groups as $group) {
$this->objectGroups[$group->id] = $group; $this->objectGroups[$group->id] = $group;
} }
/** @var \stdClass $entry */ /** @var \stdClass $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
$this->grouped[(int) $entry->object_groupable_id] = (int) $entry->object_group_id; $this->grouped[(int) $entry->object_groupable_id] = (int) $entry->object_group_id;
} }
$this->collection->transform(function (Account $account) { $this->collection->transform(function (Account $account) {
$account->object_group_id = $this->grouped[$account->id] ?? null; $account->object_group_id = $this->grouped[$account->id] ?? null;
if(null !== $account->object_group_id) { if (null !== $account->object_group_id) {
$account->object_group_title = $this->objectGroups[$account->object_group_id]->title; $account->object_group_title = $this->objectGroups[$account->object_group_id]->title;
$account->object_group_order = $this->objectGroups[$account->object_group_id]->order; $account->object_group_order = $this->objectGroups[$account->object_group_id]->order;
} }
return $account; return $account;
}); });
} }
} }

View File

@@ -62,6 +62,7 @@ trait ExpandsQuery
foreach ($value as $entry) { foreach ($value as $entry) {
$return = array_merge($return, $this->mapAccountTypes($entry)); $return = array_merge($return, $this->mapAccountTypes($entry));
} }
return array_unique($return); return array_unique($return);
} }
@@ -70,7 +71,7 @@ trait ExpandsQuery
$config = config('api.valid_api_filters')[$class]; $config = config('api.valid_api_filters')[$class];
$parsed = []; $parsed = [];
foreach ($filters->all() as $filter) { foreach ($filters->all() as $filter) {
$key = $filter->key(); $key = $filter->key();
if (!in_array($key, $config, true)) { if (!in_array($key, $config, true)) {
continue; continue;
} }
@@ -86,12 +87,16 @@ trait ExpandsQuery
switch ($filter->key()) { switch ($filter->key()) {
case 'name': case 'name':
$parsed['name'] = $value; $parsed['name'] = $value;
break; break;
case 'type': case 'type':
$parsed['type'] = $this->parseAccountTypeFilter($value); $parsed['type'] = $this->parseAccountTypeFilter($value);
break; break;
} }
} }
return $parsed; return $parsed;
} }
@@ -122,14 +127,13 @@ trait ExpandsQuery
}); });
// TODO this is special treatment, but alas, unavoidable right now. // TODO this is special treatment, but alas, unavoidable right now.
if ($class === Account::class && array_key_exists('type', $parsed)) { if (Account::class === $class && array_key_exists('type', $parsed)) {
if (count($parsed['type']) > 0) { if (count($parsed['type']) > 0) {
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); $query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
$query->whereIn('account_types.type', $parsed['type']); $query->whereIn('account_types.type', $parsed['type']);
} }
} }
return $query; return $query;
} }
} }

View File

@@ -31,24 +31,18 @@ use LaravelJsonApi\Core\Query\SortFields;
trait SortsQueryResults trait SortsQueryResults
{ {
final protected function postQuerySort(string $class, Collection $collection, SortFields $parameters): Collection final protected function postQuerySort(string $class, Collection $collection, SortFields $parameters): Collection
{ {
Log::debug(__METHOD__); Log::debug(__METHOD__);
foreach ($parameters->all() as $field) { foreach ($parameters->all() as $field) {
$collection = $this->sortQueryCollection($class, $collection, $field); $collection = $this->sortQueryCollection($class, $collection, $field);
} }
return $collection; return $collection;
} }
/** /**
* TODO improve this. * TODO improve this.
*
* @param string $class
* @param Collection $collection
* @param SortField $field
*
* @return Collection
*/ */
private function sortQueryCollection(string $class, Collection $collection, SortField $field): Collection private function sortQueryCollection(string $class, Collection $collection, SortField $field): Collection
{ {
@@ -59,6 +53,7 @@ trait SortsQueryResults
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int { $collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftSum = $this->sumBalance($left->balance); $leftSum = $this->sumBalance($left->balance);
$rightSum = $this->sumBalance($right->balance); $rightSum = $this->sumBalance($right->balance);
return $ascending ? bccomp($leftSum, $rightSum) : bccomp($rightSum, $leftSum); return $ascending ? bccomp($leftSum, $rightSum) : bccomp($rightSum, $leftSum);
}); });
} }
@@ -67,6 +62,7 @@ trait SortsQueryResults
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int { $collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftSum = $this->sumBalanceDifference($left->balance); $leftSum = $this->sumBalanceDifference($left->balance);
$rightSum = $this->sumBalanceDifference($right->balance); $rightSum = $this->sumBalanceDifference($right->balance);
return $ascending ? bccomp($leftSum, $rightSum) : bccomp($rightSum, $leftSum); return $ascending ? bccomp($leftSum, $rightSum) : bccomp($rightSum, $leftSum);
}); });
} }
@@ -76,6 +72,7 @@ trait SortsQueryResults
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int { $collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftNr = sprintf('%s%s', $left->iban, $left->account_number); $leftNr = sprintf('%s%s', $left->iban, $left->account_number);
$rightNr = sprintf('%s%s', $right->iban, $right->account_number); $rightNr = sprintf('%s%s', $right->iban, $right->account_number);
return $ascending ? strcmp($leftNr, $rightNr) : strcmp($rightNr, $leftNr); return $ascending ? strcmp($leftNr, $rightNr) : strcmp($rightNr, $leftNr);
}); });
} }
@@ -86,17 +83,17 @@ trait SortsQueryResults
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int { $collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftNr = (int)$left->last_activity?->format('U'); $leftNr = (int)$left->last_activity?->format('U');
$rightNr = (int)$right->last_activity?->format('U'); $rightNr = (int)$right->last_activity?->format('U');
if($ascending){ if ($ascending) {
return $leftNr <=> $rightNr; return $leftNr <=> $rightNr;
} }
return $rightNr <=> $leftNr; return $rightNr <=> $leftNr;
//return (int) ($ascending ? $rightNr < $leftNr : $leftNr < $rightNr ); // return (int) ($ascending ? $rightNr < $leftNr : $leftNr < $rightNr );
}); });
} }
// sort by balance difference. // sort by balance difference.
return $collection; return $collection;
} }
@@ -112,6 +109,7 @@ trait SortsQueryResults
foreach ($balance as $entry) { foreach ($balance as $entry) {
$sum = bcadd($sum, $entry['balance']); $sum = bcadd($sum, $entry['balance']);
} }
return $sum; return $sum;
} }
@@ -127,7 +125,7 @@ trait SortsQueryResults
foreach ($balance as $entry) { foreach ($balance as $entry) {
$sum = bcadd($sum, $entry['balance_difference']); $sum = bcadd($sum, $entry['balance_difference']);
} }
return $sum; return $sum;
} }
} }

View File

@@ -38,6 +38,7 @@ trait ValidateSortParameters
foreach ($params->all() as $field) { foreach ($params->all() as $field) {
if (in_array($field->name(), $config, true)) { if (in_array($field->name(), $config, true)) {
Log::debug('TRUE'); Log::debug('TRUE');
return true; return true;
} }
} }

View File

@@ -45,25 +45,28 @@ class Steam
public function balanceIgnoreVirtual(Account $account, Carbon $date): string public function balanceIgnoreVirtual(Account $account, Carbon $date): string
{ {
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__)); Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
/** @var AccountRepositoryInterface $repository */ /** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class); $repository = app(AccountRepositoryInterface::class);
$repository->setUser($account->user); $repository->setUser($account->user);
$currencyId = (int) $repository->getMetaValue($account, 'currency_id'); $currencyId = (int) $repository->getMetaValue($account, 'currency_id');
$transactions = $account->transactions() $transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currencyId) ->where('transactions.transaction_currency_id', $currencyId)
->get(['transactions.amount'])->toArray(); ->get(['transactions.amount'])->toArray()
$nativeBalance = $this->sumTransactions($transactions, 'amount'); ;
$nativeBalance = $this->sumTransactions($transactions, 'amount');
// get all balances in foreign currency: // get all balances in foreign currency:
$transactions = $account->transactions() $transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.foreign_currency_id', $currencyId) ->where('transactions.foreign_currency_id', $currencyId)
->where('transactions.transaction_currency_id', '!=', $currencyId) ->where('transactions.transaction_currency_id', '!=', $currencyId)
->get(['transactions.foreign_amount'])->toArray(); ->get(['transactions.foreign_amount'])->toArray()
;
$foreignBalance = $this->sumTransactions($transactions, 'foreign_amount'); $foreignBalance = $this->sumTransactions($transactions, 'foreign_amount');
@@ -94,7 +97,7 @@ class Steam
public function balanceInRange(Account $account, Carbon $start, Carbon $end, ?TransactionCurrency $currency = null): array public function balanceInRange(Account $account, Carbon $start, Carbon $end, ?TransactionCurrency $currency = null): array
{ {
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__)); Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($account->id); $cache->addProperty($account->id);
$cache->addProperty('balance-in-range'); $cache->addProperty('balance-in-range');
$cache->addProperty(null !== $currency ? $currency->id : 0); $cache->addProperty(null !== $currency ? $currency->id : 0);
@@ -106,41 +109,42 @@ class Steam
$start->subDay(); $start->subDay();
$end->addDay(); $end->addDay();
$balances = []; $balances = [];
$formatted = $start->format('Y-m-d'); $formatted = $start->format('Y-m-d');
$startBalance = $this->balance($account, $start, $currency); $startBalance = $this->balance($account, $start, $currency);
$balances[$formatted] = $startBalance; $balances[$formatted] = $startBalance;
if (null === $currency) { if (null === $currency) {
$repository = app(AccountRepositoryInterface::class); $repository = app(AccountRepositoryInterface::class);
$repository->setUser($account->user); $repository->setUser($account->user);
$currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup); $currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
} }
$currencyId = $currency->id; $currencyId = $currency->id;
$start->addDay(); $start->addDay();
// query! // query!
$set = $account->transactions() $set = $account->transactions()
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00')) ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59'))
->groupBy('transaction_journals.date') ->groupBy('transaction_journals.date')
->groupBy('transactions.transaction_currency_id') ->groupBy('transactions.transaction_currency_id')
->groupBy('transactions.foreign_currency_id') ->groupBy('transactions.foreign_currency_id')
->orderBy('transaction_journals.date', 'ASC') ->orderBy('transaction_journals.date', 'ASC')
->whereNull('transaction_journals.deleted_at') ->whereNull('transaction_journals.deleted_at')
->get( ->get(
[ // @phpstan-ignore-line [ // @phpstan-ignore-line
'transaction_journals.date', 'transaction_journals.date',
'transactions.transaction_currency_id', 'transactions.transaction_currency_id',
\DB::raw('SUM(transactions.amount) AS modified'), \DB::raw('SUM(transactions.amount) AS modified'),
'transactions.foreign_currency_id', 'transactions.foreign_currency_id',
\DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'), \DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'),
] ]
); )
;
$currentBalance = $startBalance; $currentBalance = $startBalance;
/** @var Transaction $entry */ /** @var Transaction $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
@@ -170,7 +174,7 @@ class Steam
public function balanceByTransactions(Account $account, Carbon $date, ?TransactionCurrency $currency): array public function balanceByTransactions(Account $account, Carbon $date, ?TransactionCurrency $currency): array
{ {
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($account->id); $cache->addProperty($account->id);
$cache->addProperty('balance-by-transactions'); $cache->addProperty('balance-by-transactions');
$cache->addProperty($date); $cache->addProperty($date);
@@ -179,12 +183,13 @@ class Steam
return $cache->get(); return $cache->get();
} }
$query = $account->transactions() $query = $account->transactions()
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->orderBy('transaction_journals.date', 'desc') ->orderBy('transaction_journals.date', 'desc')
->orderBy('transaction_journals.order', 'asc') ->orderBy('transaction_journals.order', 'asc')
->orderBy('transaction_journals.description', 'desc') ->orderBy('transaction_journals.description', 'desc')
->orderBy('transactions.amount', 'desc'); ->orderBy('transactions.amount', 'desc')
;
if (null !== $currency) { if (null !== $currency) {
$query->where('transactions.transaction_currency_id', $currency->id); $query->where('transactions.transaction_currency_id', $currency->id);
$query->limit(1); $query->limit(1);
@@ -192,18 +197,20 @@ class Steam
$key = (int) $result->transaction_currency_id; $key = (int) $result->transaction_currency_id;
$return = [$key => $result->balance_after]; $return = [$key => $result->balance_after];
$cache->store($return); $cache->store($return);
return $return; return $return;
} }
$return = []; $return = [];
$result = $query->get(['transactions.transaction_currency_id', 'transactions.balance_after']); $result = $query->get(['transactions.transaction_currency_id', 'transactions.balance_after']);
foreach ($result as $entry) { foreach ($result as $entry) {
$key = (int) $entry->transaction_currency_id; $key = (int) $entry->transaction_currency_id;
if (array_key_exists($key, $return)) { if (array_key_exists($key, $return)) {
continue; continue;
} }
$return[$key] = $entry->balance_after; $return[$key] = $entry->balance_after;
} }
return $return; return $return;
} }
@@ -216,7 +223,7 @@ class Steam
{ {
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__)); Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
// abuse chart properties: // abuse chart properties:
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($account->id); $cache->addProperty($account->id);
$cache->addProperty('balance'); $cache->addProperty('balance');
$cache->addProperty($date); $cache->addProperty($date);
@@ -226,24 +233,26 @@ class Steam
} }
/** @var AccountRepositoryInterface $repository */ /** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class); $repository = app(AccountRepositoryInterface::class);
if (null === $currency) { if (null === $currency) {
$currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup); $currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
} }
// first part: get all balances in own currency: // first part: get all balances in own currency:
$transactions = $account->transactions() $transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currency->id) ->where('transactions.transaction_currency_id', $currency->id)
->get(['transactions.amount'])->toArray(); ->get(['transactions.amount'])->toArray()
$nativeBalance = $this->sumTransactions($transactions, 'amount'); ;
$nativeBalance = $this->sumTransactions($transactions, 'amount');
// get all balances in foreign currency: // get all balances in foreign currency:
$transactions = $account->transactions() $transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.foreign_currency_id', $currency->id) ->where('transactions.foreign_currency_id', $currency->id)
->where('transactions.transaction_currency_id', '!=', $currency->id) ->where('transactions.transaction_currency_id', '!=', $currency->id)
->get(['transactions.foreign_amount'])->toArray(); ->get(['transactions.foreign_amount'])->toArray()
;
$foreignBalance = $this->sumTransactions($transactions, 'foreign_amount'); $foreignBalance = $this->sumTransactions($transactions, 'foreign_amount');
$balance = bcadd($nativeBalance, $foreignBalance); $balance = bcadd($nativeBalance, $foreignBalance);
$virtual = null === $account->virtual_balance ? '0' : $account->virtual_balance; $virtual = null === $account->virtual_balance ? '0' : $account->virtual_balance;
@@ -262,7 +271,7 @@ class Steam
public function balanceInRangeConverted(Account $account, Carbon $start, Carbon $end, TransactionCurrency $native): array public function balanceInRangeConverted(Account $account, Carbon $start, Carbon $end, TransactionCurrency $native): array
{ {
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__)); Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($account->id); $cache->addProperty($account->id);
$cache->addProperty('balance-in-range-converted'); $cache->addProperty('balance-in-range-converted');
$cache->addProperty($native->id); $cache->addProperty($native->id);
@@ -282,34 +291,35 @@ class Steam
Log::debug(sprintf('Start balance on %s is %s', $formatted, $startBalance)); Log::debug(sprintf('Start balance on %s is %s', $formatted, $startBalance));
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__)); Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
// not sure why this is happening: // not sure why this is happening:
$start->addDay(); $start->addDay();
// grab all transactions between start and end: // grab all transactions between start and end:
$set = $account->transactions() $set = $account->transactions()
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00')) ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59'))
->orderBy('transaction_journals.date', 'ASC') ->orderBy('transaction_journals.date', 'ASC')
->whereNull('transaction_journals.deleted_at') ->whereNull('transaction_journals.deleted_at')
->get( ->get(
[ [
'transaction_journals.date', 'transaction_journals.date',
'transactions.transaction_currency_id', 'transactions.transaction_currency_id',
'transactions.amount', 'transactions.amount',
'transactions.foreign_currency_id', 'transactions.foreign_currency_id',
'transactions.foreign_amount', 'transactions.foreign_amount',
] ]
)->toArray(); )->toArray()
;
// loop the set and convert if necessary: // loop the set and convert if necessary:
$currentBalance = $startBalance; $currentBalance = $startBalance;
/** @var Transaction $transaction */ /** @var Transaction $transaction */
foreach ($set as $transaction) { foreach ($set as $transaction) {
$day = false; $day = false;
try { try {
$day = Carbon::parse($transaction['date'], config('app.timezone')); $day = Carbon::parse($transaction['date'], config('app.timezone'));
@@ -319,7 +329,7 @@ class Steam
if (false === $day) { if (false === $day) {
$day = today(config('app.timezone')); $day = today(config('app.timezone'));
} }
$format = $day->format('Y-m-d'); $format = $day->format('Y-m-d');
// if the transaction is in the expected currency, change nothing. // if the transaction is in the expected currency, change nothing.
if ((int) $transaction['transaction_currency_id'] === $native->id) { if ((int) $transaction['transaction_currency_id'] === $native->id) {
// change the current balance, set it to today, continue the loop. // change the current balance, set it to today, continue the loop.
@@ -342,21 +352,21 @@ class Steam
$currency = $currencies[$currencyId] ?? TransactionCurrency::find($currencyId); $currency = $currencies[$currencyId] ?? TransactionCurrency::find($currencyId);
$currencies[$currencyId] = $currency; $currencies[$currencyId] = $currency;
$rate = $converter->getCurrencyRate($currency, $native, $day); $rate = $converter->getCurrencyRate($currency, $native, $day);
$convertedAmount = bcmul($transaction['amount'], $rate); $convertedAmount = bcmul($transaction['amount'], $rate);
$currentBalance = bcadd($currentBalance, $convertedAmount); $currentBalance = bcadd($currentBalance, $convertedAmount);
$balances[$format] = $currentBalance; $balances[$format] = $currentBalance;
Log::debug(sprintf( Log::debug(sprintf(
'%s: transaction in %s(!). Conversion rate is %s. %s %s = %s %s', '%s: transaction in %s(!). Conversion rate is %s. %s %s = %s %s',
$format, $format,
$currency->code, $currency->code,
$rate, $rate,
$currency->code, $currency->code,
$transaction['amount'], $transaction['amount'],
$native->code, $native->code,
$convertedAmount $convertedAmount
)); ));
} }
$cache->store($balances); $cache->store($balances);
@@ -388,7 +398,7 @@ class Steam
{ {
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__)); Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
Log::debug(sprintf('Now in balanceConverted (%s) for account #%d, converting to %s', $date->format('Y-m-d'), $account->id, $native->code)); Log::debug(sprintf('Now in balanceConverted (%s) for account #%d, converting to %s', $date->format('Y-m-d'), $account->id, $native->code));
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($account->id); $cache->addProperty($account->id);
$cache->addProperty('balance'); $cache->addProperty('balance');
$cache->addProperty($date); $cache->addProperty($date);
@@ -396,7 +406,7 @@ class Steam
if ($cache->has()) { if ($cache->has()) {
Log::debug('Cached!'); Log::debug('Cached!');
return $cache->get(); return $cache->get();
} }
/** @var AccountRepositoryInterface $repository */ /** @var AccountRepositoryInterface $repository */
@@ -409,66 +419,72 @@ class Steam
return $this->balance($account, $date); return $this->balance($account, $date);
} }
$new = []; $new = [];
$existing = []; $existing = [];
$new[] = $account->transactions() // 1 $new[] = $account->transactions() // 1
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currency->id) ->where('transactions.transaction_currency_id', $currency->id)
->whereNull('transactions.foreign_currency_id') ->whereNull('transactions.foreign_currency_id')
->get(['transaction_journals.date', 'transactions.amount'])->toArray(); ->get(['transaction_journals.date', 'transactions.amount'])->toArray()
;
Log::debug(sprintf('%d transaction(s) in set #1', count($new[0]))); Log::debug(sprintf('%d transaction(s) in set #1', count($new[0])));
$existing[] = $account->transactions() // 2 $existing[] = $account->transactions() // 2
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $native->id) ->where('transactions.transaction_currency_id', $native->id)
->whereNull('transactions.foreign_currency_id') ->whereNull('transactions.foreign_currency_id')
->get(['transactions.amount'])->toArray(); ->get(['transactions.amount'])->toArray()
;
Log::debug(sprintf('%d transaction(s) in set #2', count($existing[0]))); Log::debug(sprintf('%d transaction(s) in set #2', count($existing[0])));
$new[] = $account->transactions() // 3 $new[] = $account->transactions() // 3
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', '!=', $currency->id) ->where('transactions.transaction_currency_id', '!=', $currency->id)
->where('transactions.transaction_currency_id', '!=', $native->id) ->where('transactions.transaction_currency_id', '!=', $native->id)
->whereNull('transactions.foreign_currency_id') ->whereNull('transactions.foreign_currency_id')
->get(['transaction_journals.date', 'transactions.amount'])->toArray(); ->get(['transaction_journals.date', 'transactions.amount'])->toArray()
;
Log::debug(sprintf('%d transactions in set #3', count($new[1]))); Log::debug(sprintf('%d transactions in set #3', count($new[1])));
$existing[] = $account->transactions() // 4 $existing[] = $account->transactions() // 4
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.foreign_currency_id', $native->id) ->where('transactions.foreign_currency_id', $native->id)
->whereNotNull('transactions.foreign_amount') ->whereNotNull('transactions.foreign_amount')
->get(['transactions.foreign_amount'])->toArray(); ->get(['transactions.foreign_amount'])->toArray()
;
Log::debug(sprintf('%d transactions in set #4', count($existing[1]))); Log::debug(sprintf('%d transactions in set #4', count($existing[1])));
$new[] = $account->transactions()// 5 $new[] = $account->transactions()// 5
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currency->id) ->where('transactions.transaction_currency_id', $currency->id)
->where('transactions.foreign_currency_id', '!=', $native->id) ->where('transactions.foreign_currency_id', '!=', $native->id)
->whereNotNull('transactions.foreign_amount') ->whereNotNull('transactions.foreign_amount')
->get(['transaction_journals.date', 'transactions.amount'])->toArray(); ->get(['transaction_journals.date', 'transactions.amount'])->toArray()
;
Log::debug(sprintf('%d transactions in set #5', count($new[2]))); Log::debug(sprintf('%d transactions in set #5', count($new[2])));
$new[] = $account->transactions()// 6 $new[] = $account->transactions()// 6
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', '!=', $currency->id) ->where('transactions.transaction_currency_id', '!=', $currency->id)
->where('transactions.foreign_currency_id', '!=', $native->id) ->where('transactions.foreign_currency_id', '!=', $native->id)
->whereNotNull('transactions.foreign_amount') ->whereNotNull('transactions.foreign_amount')
->get(['transaction_journals.date', 'transactions.amount'])->toArray(); ->get(['transaction_journals.date', 'transactions.amount'])->toArray()
;
Log::debug(sprintf('%d transactions in set #6', count($new[3]))); Log::debug(sprintf('%d transactions in set #6', count($new[3])));
// process both sets of transactions. Of course, no need to convert set "existing". // process both sets of transactions. Of course, no need to convert set "existing".
$balance = $this->sumTransactions($existing[0], 'amount'); $balance = $this->sumTransactions($existing[0], 'amount');
$balance = bcadd($balance, $this->sumTransactions($existing[1], 'foreign_amount')); $balance = bcadd($balance, $this->sumTransactions($existing[1], 'foreign_amount'));
Log::debug(sprintf('Balance from set #2 and #4 is %f', $balance)); Log::debug(sprintf('Balance from set #2 and #4 is %f', $balance));
// need to convert the others. All sets use the "amount" value as their base (that's easy) // need to convert the others. All sets use the "amount" value as their base (that's easy)
// but we need to convert each transaction separately because the date difference may // but we need to convert each transaction separately because the date difference may
// incur huge currency changes. // incur huge currency changes.
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__)); Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
$start = clone $date; $start = clone $date;
$end = clone $date; $end = clone $date;
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
foreach ($new as $set) { foreach ($new as $set) {
foreach ($set as $transaction) { foreach ($set as $transaction) {
$currentDate = false; $currentDate = false;
@@ -491,7 +507,7 @@ class Steam
foreach ($new as $set) { foreach ($new as $set) {
foreach ($set as $transaction) { foreach ($set as $transaction) {
$currentDate = false; $currentDate = false;
try { try {
$currentDate = Carbon::parse($transaction['date'], config('app.timezone')); $currentDate = Carbon::parse($transaction['date'], config('app.timezone'));
@@ -508,9 +524,9 @@ class Steam
} }
// add virtual balance (also needs conversion) // add virtual balance (also needs conversion)
$virtual = null === $account->virtual_balance ? '0' : $account->virtual_balance; $virtual = null === $account->virtual_balance ? '0' : $account->virtual_balance;
$virtual = $converter->convert($currency, $native, $account->created_at, $virtual); $virtual = $converter->convert($currency, $native, $account->created_at, $virtual);
$balance = bcadd($balance, $virtual); $balance = bcadd($balance, $virtual);
$converter->summarize(); $converter->summarize();
$cache->store($balance); $cache->store($balance);
@@ -527,9 +543,9 @@ class Steam
public function balancesByAccounts(Collection $accounts, Carbon $date): array public function balancesByAccounts(Collection $accounts, Carbon $date): array
{ {
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__)); Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$ids = $accounts->pluck('id')->toArray(); $ids = $accounts->pluck('id')->toArray();
// cache this property. // cache this property.
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($ids); $cache->addProperty($ids);
$cache->addProperty('balances'); $cache->addProperty('balances');
$cache->addProperty($date); $cache->addProperty($date);
@@ -558,14 +574,14 @@ class Steam
public function balancesByAccountsConverted(Collection $accounts, Carbon $date): array public function balancesByAccountsConverted(Collection $accounts, Carbon $date): array
{ {
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__)); Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$ids = $accounts->pluck('id')->toArray(); $ids = $accounts->pluck('id')->toArray();
// cache this property. // cache this property.
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($ids); $cache->addProperty($ids);
$cache->addProperty('balances-converted'); $cache->addProperty('balances-converted');
$cache->addProperty($date); $cache->addProperty($date);
if ($cache->has()) { if ($cache->has()) {
return $cache->get(); return $cache->get();
} }
// need to do this per account. // need to do this per account.
@@ -576,9 +592,9 @@ class Steam
$default = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup); $default = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
$result[$account->id] $result[$account->id]
= [ = [
'balance' => $this->balance($account, $date), 'balance' => $this->balance($account, $date),
'native_balance' => $this->balanceConverted($account, $date, $default), 'native_balance' => $this->balanceConverted($account, $date, $default),
]; ];
} }
$cache->store($result); $cache->store($result);
@@ -592,9 +608,9 @@ class Steam
public function balancesPerCurrencyByAccounts(Collection $accounts, Carbon $date): array public function balancesPerCurrencyByAccounts(Collection $accounts, Carbon $date): array
{ {
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__)); Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$ids = $accounts->pluck('id')->toArray(); $ids = $accounts->pluck('id')->toArray();
// cache this property. // cache this property.
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($ids); $cache->addProperty($ids);
$cache->addProperty('balances-per-currency'); $cache->addProperty('balances-per-currency');
$cache->addProperty($date); $cache->addProperty($date);
@@ -619,7 +635,7 @@ class Steam
{ {
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__)); Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
// abuse chart properties: // abuse chart properties:
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($account->id); $cache->addProperty($account->id);
$cache->addProperty('balance-per-currency'); $cache->addProperty('balance-per-currency');
$cache->addProperty($date); $cache->addProperty($date);
@@ -627,9 +643,10 @@ class Steam
return $cache->get(); return $cache->get();
} }
$query = $account->transactions() $query = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->groupBy('transactions.transaction_currency_id'); ->groupBy('transactions.transaction_currency_id')
;
$balances = $query->get(['transactions.transaction_currency_id', \DB::raw('SUM(transactions.amount) as sum_for_currency')]); // @phpstan-ignore-line $balances = $query->get(['transactions.transaction_currency_id', \DB::raw('SUM(transactions.amount) as sum_for_currency')]); // @phpstan-ignore-line
$return = []; $return = [];
@@ -661,10 +678,10 @@ class Steam
// Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision)); // Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision));
if (str_contains($number, '.')) { if (str_contains($number, '.')) {
if ('-' !== $number[0]) { if ('-' !== $number[0]) {
return bcadd($number, '0.' . str_repeat('0', $precision) . '5', $precision); return bcadd($number, '0.'.str_repeat('0', $precision).'5', $precision);
} }
return bcsub($number, '0.' . str_repeat('0', $precision) . '5', $precision); return bcsub($number, '0.'.str_repeat('0', $precision).'5', $precision);
} }
return $number; return $number;
@@ -747,15 +764,15 @@ class Steam
{ {
$list = []; $list = [];
$set = auth()->user()->transactions() $set = auth()->user()->transactions()
->whereIn('transactions.account_id', $accounts) ->whereIn('transactions.account_id', $accounts)
->groupBy(['transactions.account_id', 'transaction_journals.user_id']) ->groupBy(['transactions.account_id', 'transaction_journals.user_id'])
->get(['transactions.account_id', \DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line ->get(['transactions.account_id', \DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line
; ;
/** @var Transaction $entry */ /** @var Transaction $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
$date = new Carbon($entry->max_date, config('app.timezone')); $date = new Carbon($entry->max_date, config('app.timezone'));
$date->setTimezone(config('app.timezone')); $date->setTimezone(config('app.timezone'));
$list[$entry->account_id] = $date; $list[$entry->account_id] = $date;
} }
@@ -830,9 +847,9 @@ class Steam
public function getSafeUrl(string $unknownUrl, string $safeUrl): string public function getSafeUrl(string $unknownUrl, string $safeUrl): string
{ {
// Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl)); // Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl));
$returnUrl = $safeUrl; $returnUrl = $safeUrl;
$unknownHost = parse_url($unknownUrl, PHP_URL_HOST); $unknownHost = parse_url($unknownUrl, PHP_URL_HOST);
$safeHost = parse_url($safeUrl, PHP_URL_HOST); $safeHost = parse_url($safeUrl, PHP_URL_HOST);
if (null !== $unknownHost && $unknownHost === $safeHost) { if (null !== $unknownHost && $unknownHost === $safeHost) {
$returnUrl = $unknownUrl; $returnUrl = $unknownUrl;
@@ -869,7 +886,7 @@ class Steam
*/ */
public function floatalize(string $value): string public function floatalize(string $value): string
{ {
$value = strtoupper($value); $value = strtoupper($value);
if (!str_contains($value, 'E')) { if (!str_contains($value, 'E')) {
return $value; return $value;
} }

View File

@@ -63,15 +63,16 @@ class General extends AbstractExtension
} }
/** @var Carbon $date */ /** @var Carbon $date */
$date = session('end', today(config('app.timezone'))->endOfMonth()); $date = session('end', today(config('app.timezone'))->endOfMonth());
$info = app('steam')->balanceByTransactions($account, $date, null); $info = app('steam')->balanceByTransactions($account, $date, null);
$strings = []; $strings = [];
foreach($info as $currencyId => $balance) { foreach ($info as $currencyId => $balance) {
$strings[] = app('amount')->formatByCurrencyId($currencyId, $balance, false); $strings[] = app('amount')->formatByCurrencyId($currencyId, $balance, false);
} }
return implode(', ', $strings); return implode(', ', $strings);
//return app('steam')->balance($account, $date); // return app('steam')->balance($account, $date);
} }
); );
} }

46
composer.lock generated
View File

@@ -4344,23 +4344,23 @@
}, },
{ {
"name": "nunomaduro/collision", "name": "nunomaduro/collision",
"version": "v8.3.0", "version": "v8.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nunomaduro/collision.git", "url": "https://github.com/nunomaduro/collision.git",
"reference": "b49f5b2891ce52726adfd162841c69d4e4c84229" "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/b49f5b2891ce52726adfd162841c69d4e4c84229", "url": "https://api.github.com/repos/nunomaduro/collision/zipball/e7d1aa8ed753f63fa816932bbc89678238843b4a",
"reference": "b49f5b2891ce52726adfd162841c69d4e4c84229", "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"filp/whoops": "^2.15.4", "filp/whoops": "^2.15.4",
"nunomaduro/termwind": "^2.0.1", "nunomaduro/termwind": "^2.0.1",
"php": "^8.2.0", "php": "^8.2.0",
"symfony/console": "^7.1.2" "symfony/console": "^7.1.3"
}, },
"conflict": { "conflict": {
"laravel/framework": "<11.0.0 || >=12.0.0", "laravel/framework": "<11.0.0 || >=12.0.0",
@@ -4368,13 +4368,13 @@
}, },
"require-dev": { "require-dev": {
"larastan/larastan": "^2.9.8", "larastan/larastan": "^2.9.8",
"laravel/framework": "^11.16.0", "laravel/framework": "^11.19.0",
"laravel/pint": "^1.16.2", "laravel/pint": "^1.17.1",
"laravel/sail": "^1.30.2", "laravel/sail": "^1.31.0",
"laravel/sanctum": "^4.0.2", "laravel/sanctum": "^4.0.2",
"laravel/tinker": "^2.9.0", "laravel/tinker": "^2.9.0",
"orchestra/testbench-core": "^9.2.1", "orchestra/testbench-core": "^9.2.3",
"pestphp/pest": "^2.34.9 || ^3.0.0", "pestphp/pest": "^2.35.0 || ^3.0.0",
"sebastian/environment": "^6.1.0 || ^7.0.0" "sebastian/environment": "^6.1.0 || ^7.0.0"
}, },
"type": "library", "type": "library",
@@ -4437,7 +4437,7 @@
"type": "patreon" "type": "patreon"
} }
], ],
"time": "2024-07-16T22:41:01+00:00" "time": "2024-08-03T15:32:23+00:00"
}, },
{ {
"name": "nunomaduro/termwind", "name": "nunomaduro/termwind",
@@ -6046,16 +6046,16 @@
}, },
{ {
"name": "spatie/flare-client-php", "name": "spatie/flare-client-php",
"version": "1.7.0", "version": "1.8.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/flare-client-php.git", "url": "https://github.com/spatie/flare-client-php.git",
"reference": "097040ff51e660e0f6fc863684ac4b02c93fa234" "reference": "180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/flare-client-php/zipball/097040ff51e660e0f6fc863684ac4b02c93fa234", "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122",
"reference": "097040ff51e660e0f6fc863684ac4b02c93fa234", "reference": "180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6073,7 +6073,7 @@
"phpstan/extension-installer": "^1.1", "phpstan/extension-installer": "^1.1",
"phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-phpunit": "^1.0",
"spatie/phpunit-snapshot-assertions": "^4.0|^5.0" "spatie/pest-plugin-snapshots": "^1.0|^2.0"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@@ -6103,7 +6103,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/spatie/flare-client-php/issues", "issues": "https://github.com/spatie/flare-client-php/issues",
"source": "https://github.com/spatie/flare-client-php/tree/1.7.0" "source": "https://github.com/spatie/flare-client-php/tree/1.8.0"
}, },
"funding": [ "funding": [
{ {
@@ -6111,7 +6111,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-06-12T14:39:14+00:00" "time": "2024-08-01T08:27:26+00:00"
}, },
{ {
"name": "spatie/ignition", "name": "spatie/ignition",
@@ -11225,16 +11225,16 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "1.11.8", "version": "1.11.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec" "reference": "e370bcddadaede0c1716338b262346f40d296f82"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e370bcddadaede0c1716338b262346f40d296f82",
"reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec", "reference": "e370bcddadaede0c1716338b262346f40d296f82",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -11279,7 +11279,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-07-24T07:01:22+00:00" "time": "2024-08-01T16:25:18+00:00"
}, },
{ {
"name": "phpstan/phpstan-deprecation-rules", "name": "phpstan/phpstan-deprecation-rules",

View File

@@ -24,7 +24,6 @@ declare(strict_types=1);
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
return [ return [
// allowed filters (search) for APIs // allowed filters (search) for APIs
'filters' => [ 'filters' => [
'allowed' => [ 'allowed' => [

View File

@@ -117,7 +117,7 @@ return [
'expression_engine' => true, 'expression_engine' => true,
// see cer.php for exchange rates feature flag. // see cer.php for exchange rates feature flag.
], ],
'version' => 'develop/2024-07-29', 'version' => 'develop/2024-08-05',
'api_version' => '2.1.0', 'api_version' => '2.1.0',
'db_version' => 24, 'db_version' => 24,
@@ -919,5 +919,4 @@ return [
// preselected account lists possibilities: // preselected account lists possibilities:
'preselected_accounts' => ['all', 'assets', 'liabilities'], 'preselected_accounts' => ['all', 'assets', 'liabilities'],
]; ];

391
package-lock.json generated
View File

@@ -69,30 +69,30 @@
} }
}, },
"node_modules/@babel/compat-data": { "node_modules/@babel/compat-data": {
"version": "7.25.0", "version": "7.25.2",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.0.tgz", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz",
"integrity": "sha512-P4fwKI2mjEb3ZU5cnMJzvRsRKGBUcs8jvxIoRmr6ufAY9Xk2Bz7JubRTTivkw55c7WQJfTECeqYVa+HZ0FzREg==", "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/core": { "node_modules/@babel/core": {
"version": "7.24.9", "version": "7.25.2",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz",
"integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@ampproject/remapping": "^2.2.0", "@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.24.7", "@babel/code-frame": "^7.24.7",
"@babel/generator": "^7.24.9", "@babel/generator": "^7.25.0",
"@babel/helper-compilation-targets": "^7.24.8", "@babel/helper-compilation-targets": "^7.25.2",
"@babel/helper-module-transforms": "^7.24.9", "@babel/helper-module-transforms": "^7.25.2",
"@babel/helpers": "^7.24.8", "@babel/helpers": "^7.25.0",
"@babel/parser": "^7.24.8", "@babel/parser": "^7.25.0",
"@babel/template": "^7.24.7", "@babel/template": "^7.25.0",
"@babel/traverse": "^7.24.8", "@babel/traverse": "^7.25.2",
"@babel/types": "^7.24.9", "@babel/types": "^7.25.2",
"convert-source-map": "^2.0.0", "convert-source-map": "^2.0.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"gensync": "^1.0.0-beta.2", "gensync": "^1.0.0-beta.2",
@@ -157,12 +157,12 @@
} }
}, },
"node_modules/@babel/helper-compilation-targets": { "node_modules/@babel/helper-compilation-targets": {
"version": "7.24.8", "version": "7.25.2",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz",
"integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/compat-data": "^7.24.8", "@babel/compat-data": "^7.25.2",
"@babel/helper-validator-option": "^7.24.8", "@babel/helper-validator-option": "^7.24.8",
"browserslist": "^4.23.1", "browserslist": "^4.23.1",
"lru-cache": "^5.1.1", "lru-cache": "^5.1.1",
@@ -212,9 +212,9 @@
} }
}, },
"node_modules/@babel/helper-create-regexp-features-plugin": { "node_modules/@babel/helper-create-regexp-features-plugin": {
"version": "7.25.0", "version": "7.25.2",
"resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz",
"integrity": "sha512-q0T+dknZS+L5LDazIP+02gEZITG5unzvb6yIjcmj5i0eFrs5ToBV2m2JGH4EsE/gtP8ygEGLGApBgRIZkTm7zg==", "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-annotate-as-pure": "^7.24.7",
@@ -280,15 +280,15 @@
} }
}, },
"node_modules/@babel/helper-module-transforms": { "node_modules/@babel/helper-module-transforms": {
"version": "7.25.0", "version": "7.25.2",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz",
"integrity": "sha512-bIkOa2ZJYn7FHnepzr5iX9Kmz8FjIz4UKzJ9zhX3dnYuVW0xul9RuR3skBfoLu+FPTQw90EHW9rJsSZhyLQ3fQ==", "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-module-imports": "^7.24.7", "@babel/helper-module-imports": "^7.24.7",
"@babel/helper-simple-access": "^7.24.7", "@babel/helper-simple-access": "^7.24.7",
"@babel/helper-validator-identifier": "^7.24.7", "@babel/helper-validator-identifier": "^7.24.7",
"@babel/traverse": "^7.25.0" "@babel/traverse": "^7.25.2"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -510,10 +510,13 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.25.0", "version": "7.25.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.0.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz",
"integrity": "sha512-CzdIU9jdP0dg7HdyB+bHvDJGagUv+qtzZt5rYCWwW6tITNqV9odjp6Qu41gkG0ca5UfdDUWrKkiAnHHdGRnOrA==", "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==",
"dev": true, "dev": true,
"dependencies": {
"@babel/types": "^7.25.2"
},
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
}, },
@@ -522,13 +525,13 @@
} }
}, },
"node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
"version": "7.25.0", "version": "7.25.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.0.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz",
"integrity": "sha512-dG0aApncVQwAUJa8tP1VHTnmU67BeIQvKafd3raEx315H54FfkZSz3B/TT+33ZQAjatGJA79gZqTtqL5QZUKXw==", "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8",
"@babel/traverse": "^7.25.0" "@babel/traverse": "^7.25.3"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -1176,12 +1179,12 @@
} }
}, },
"node_modules/@babel/plugin-transform-literals": { "node_modules/@babel/plugin-transform-literals": {
"version": "7.24.7", "version": "7.25.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz",
"integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-plugin-utils": "^7.24.7" "@babel/helper-plugin-utils": "^7.24.8"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -1682,16 +1685,16 @@
} }
}, },
"node_modules/@babel/preset-env": { "node_modules/@babel/preset-env": {
"version": "7.25.0", "version": "7.25.3",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.0.tgz", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz",
"integrity": "sha512-vYAA8PrCOeZfG4D87hmw1KJ1BPubghXP1e2MacRFwECGNKL76dkA38JEwYllbvQCpf/kLxsTtir0b8MtxKoVCw==", "integrity": "sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/compat-data": "^7.25.0", "@babel/compat-data": "^7.25.2",
"@babel/helper-compilation-targets": "^7.24.8", "@babel/helper-compilation-targets": "^7.25.2",
"@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8",
"@babel/helper-validator-option": "^7.24.8", "@babel/helper-validator-option": "^7.24.8",
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.0", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3",
"@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0",
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7",
@@ -1732,9 +1735,9 @@
"@babel/plugin-transform-exponentiation-operator": "^7.24.7", "@babel/plugin-transform-exponentiation-operator": "^7.24.7",
"@babel/plugin-transform-export-namespace-from": "^7.24.7", "@babel/plugin-transform-export-namespace-from": "^7.24.7",
"@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-for-of": "^7.24.7",
"@babel/plugin-transform-function-name": "^7.25.0", "@babel/plugin-transform-function-name": "^7.25.1",
"@babel/plugin-transform-json-strings": "^7.24.7", "@babel/plugin-transform-json-strings": "^7.24.7",
"@babel/plugin-transform-literals": "^7.24.7", "@babel/plugin-transform-literals": "^7.25.2",
"@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
"@babel/plugin-transform-member-expression-literals": "^7.24.7", "@babel/plugin-transform-member-expression-literals": "^7.24.7",
"@babel/plugin-transform-modules-amd": "^7.24.7", "@babel/plugin-transform-modules-amd": "^7.24.7",
@@ -1833,16 +1836,16 @@
} }
}, },
"node_modules/@babel/traverse": { "node_modules/@babel/traverse": {
"version": "7.25.1", "version": "7.25.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.1.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz",
"integrity": "sha512-LrHHoWq08ZpmmFqBAzN+hUdWwy5zt7FGa/hVwMcOqW6OVtwqaoD5utfuGYU87JYxdZgLUvktAsn37j/sYR9siA==", "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.24.7", "@babel/code-frame": "^7.24.7",
"@babel/generator": "^7.25.0", "@babel/generator": "^7.25.0",
"@babel/parser": "^7.25.0", "@babel/parser": "^7.25.3",
"@babel/template": "^7.25.0", "@babel/template": "^7.25.0",
"@babel/types": "^7.25.0", "@babel/types": "^7.25.2",
"debug": "^4.3.1", "debug": "^4.3.1",
"globals": "^11.1.0" "globals": "^11.1.0"
}, },
@@ -1851,9 +1854,9 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.25.0", "version": "7.25.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.0.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz",
"integrity": "sha512-LcnxQSsd9aXOIgmmSpvZ/1yo46ra2ESYyqLcryaBZOghxy5qqOBjvCWP5JfkI8yl9rlxRgdLTTMCQQRcN2hdCg==", "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.24.8", "@babel/helper-string-parser": "^7.24.8",
@@ -2385,9 +2388,9 @@
} }
}, },
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.20.0.tgz",
"integrity": "sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww==", "integrity": "sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -2398,9 +2401,9 @@
] ]
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.20.0.tgz",
"integrity": "sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A==", "integrity": "sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2411,9 +2414,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.20.0.tgz",
"integrity": "sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q==", "integrity": "sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2424,9 +2427,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.20.0.tgz",
"integrity": "sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA==", "integrity": "sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2437,9 +2440,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.20.0.tgz",
"integrity": "sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==", "integrity": "sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -2450,9 +2453,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-musleabihf": { "node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.20.0.tgz",
"integrity": "sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==", "integrity": "sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -2463,9 +2466,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.20.0.tgz",
"integrity": "sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==", "integrity": "sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2476,9 +2479,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.20.0.tgz",
"integrity": "sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==", "integrity": "sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2489,9 +2492,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": { "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.20.0.tgz",
"integrity": "sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==", "integrity": "sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@@ -2502,9 +2505,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.20.0.tgz",
"integrity": "sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==", "integrity": "sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@@ -2515,9 +2518,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": { "node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.20.0.tgz",
"integrity": "sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==", "integrity": "sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@@ -2528,9 +2531,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.20.0.tgz",
"integrity": "sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==", "integrity": "sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2541,9 +2544,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.20.0.tgz",
"integrity": "sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==", "integrity": "sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2554,9 +2557,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.20.0.tgz",
"integrity": "sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA==", "integrity": "sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2567,9 +2570,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.20.0.tgz",
"integrity": "sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ==", "integrity": "sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -2580,9 +2583,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.20.0.tgz",
"integrity": "sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg==", "integrity": "sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2830,12 +2833,12 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.0.0", "version": "22.1.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.0.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz",
"integrity": "sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==", "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"undici-types": "~6.11.1" "undici-types": "~6.13.0"
} }
}, },
"node_modules/@types/node-forge": { "node_modules/@types/node-forge": {
@@ -2917,62 +2920,62 @@
"dev": true "dev": true
}, },
"node_modules/@types/ws": { "node_modules/@types/ws": {
"version": "8.5.11", "version": "8.5.12",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.11.tgz", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz",
"integrity": "sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w==", "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@vue/compiler-core": { "node_modules/@vue/compiler-core": {
"version": "3.4.34", "version": "3.4.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.34.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.35.tgz",
"integrity": "sha512-Z0izUf32+wAnQewjHu+pQf1yw00EGOmevl1kE+ljjjMe7oEfpQ+BI3/JNK7yMB4IrUsqLDmPecUrpj3mCP+yJQ==", "integrity": "sha512-gKp0zGoLnMYtw4uS/SJRRO7rsVggLjvot3mcctlMXunYNsX+aRJDqqw/lV5/gHK91nvaAAlWFgdVl020AW1Prg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/parser": "^7.24.7", "@babel/parser": "^7.24.7",
"@vue/shared": "3.4.34", "@vue/shared": "3.4.35",
"entities": "^4.5.0", "entities": "^4.5.0",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"source-map-js": "^1.2.0" "source-map-js": "^1.2.0"
} }
}, },
"node_modules/@vue/compiler-dom": { "node_modules/@vue/compiler-dom": {
"version": "3.4.34", "version": "3.4.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.34.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.35.tgz",
"integrity": "sha512-3PUOTS1h5cskdOJMExCu2TInXuM0j60DRPpSCJDqOCupCfUZCJoyQmKtRmA8EgDNZ5kcEE7vketamRZfrEuVDw==", "integrity": "sha512-pWIZRL76/oE/VMhdv/ovZfmuooEni6JPG1BFe7oLk5DZRo/ImydXijoZl/4kh2406boRQ7lxTYzbZEEXEhj9NQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@vue/compiler-core": "3.4.34", "@vue/compiler-core": "3.4.35",
"@vue/shared": "3.4.34" "@vue/shared": "3.4.35"
} }
}, },
"node_modules/@vue/compiler-sfc": { "node_modules/@vue/compiler-sfc": {
"version": "3.4.34", "version": "3.4.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.34.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.35.tgz",
"integrity": "sha512-x6lm0UrM03jjDXTPZgD9Ad8bIVD1ifWNit2EaWQIZB5CULr46+FbLQ5RpK7AXtDHGjx9rmvC7QRCTjsiGkAwRw==", "integrity": "sha512-xacnRS/h/FCsjsMfxBkzjoNxyxEyKyZfBch/P4vkLRvYJwe5ChXmZZrj8Dsed/752H2Q3JE8kYu9Uyha9J6PgA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/parser": "^7.24.7", "@babel/parser": "^7.24.7",
"@vue/compiler-core": "3.4.34", "@vue/compiler-core": "3.4.35",
"@vue/compiler-dom": "3.4.34", "@vue/compiler-dom": "3.4.35",
"@vue/compiler-ssr": "3.4.34", "@vue/compiler-ssr": "3.4.35",
"@vue/shared": "3.4.34", "@vue/shared": "3.4.35",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"magic-string": "^0.30.10", "magic-string": "^0.30.10",
"postcss": "^8.4.39", "postcss": "^8.4.40",
"source-map-js": "^1.2.0" "source-map-js": "^1.2.0"
} }
}, },
"node_modules/@vue/compiler-ssr": { "node_modules/@vue/compiler-ssr": {
"version": "3.4.34", "version": "3.4.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.34.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.35.tgz",
"integrity": "sha512-8TDBcLaTrFm5rnF+Qm4BlliaopJgqJ28Nsrc80qazynm5aJO+Emu7y0RWw34L8dNnTRdcVBpWzJxhGYzsoVu4g==", "integrity": "sha512-7iynB+0KB1AAJKk/biENTV5cRGHRdbdaD7Mx3nWcm1W8bVD6QmnH3B4AHhQQ1qZHhqFwzEzMwiytXm3PX1e60A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@vue/compiler-dom": "3.4.34", "@vue/compiler-dom": "3.4.35",
"@vue/shared": "3.4.34" "@vue/shared": "3.4.35"
} }
}, },
"node_modules/@vue/component-compiler-utils": { "node_modules/@vue/component-compiler-utils": {
@@ -3047,9 +3050,9 @@
"integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==" "integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA=="
}, },
"node_modules/@vue/shared": { "node_modules/@vue/shared": {
"version": "3.4.34", "version": "3.4.35",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.34.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.35.tgz",
"integrity": "sha512-x5LmiRLpRsd9KTjAB8MPKf0CDPMcuItjP0gbNqFCIgL1I8iYp4zglhj9w9FPCdIbHG2M91RVeIbArFfFTz9I3A==", "integrity": "sha512-hvuhBYYDe+b1G8KHxsQ0diDqDMA8D9laxWZhNAjE83VZb5UDaXl9Xnz7cGdDSyiHM90qqI/CyGMcpBpiDy6VVQ==",
"dev": true "dev": true
}, },
"node_modules/@webassemblyjs/ast": { "node_modules/@webassemblyjs/ast": {
@@ -3490,9 +3493,9 @@
} }
}, },
"node_modules/autoprefixer": { "node_modules/autoprefixer": {
"version": "10.4.19", "version": "10.4.20",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
"integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -3509,11 +3512,11 @@
} }
], ],
"dependencies": { "dependencies": {
"browserslist": "^4.23.0", "browserslist": "^4.23.3",
"caniuse-lite": "^1.0.30001599", "caniuse-lite": "^1.0.30001646",
"fraction.js": "^4.3.7", "fraction.js": "^4.3.7",
"normalize-range": "^0.1.2", "normalize-range": "^0.1.2",
"picocolors": "^1.0.0", "picocolors": "^1.0.1",
"postcss-value-parser": "^4.2.0" "postcss-value-parser": "^4.2.0"
}, },
"bin": { "bin": {
@@ -3527,9 +3530,9 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.7.2", "version": "1.7.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz",
"integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
@@ -3580,13 +3583,13 @@
} }
}, },
"node_modules/babel-plugin-polyfill-corejs3": { "node_modules/babel-plugin-polyfill-corejs3": {
"version": "0.10.4", "version": "0.10.6",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz",
"integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-define-polyfill-provider": "^0.6.1", "@babel/helper-define-polyfill-provider": "^0.6.2",
"core-js-compat": "^3.36.1" "core-js-compat": "^3.38.0"
}, },
"peerDependencies": { "peerDependencies": {
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
@@ -3778,9 +3781,9 @@
"integrity": "sha512-9oBGvXilL+/1tH5uVPo8rFlUbQP05n9hdj85YFvGAwjH1NP/bRSYhHcywkBe8aFFmkQHr3oi0Creh5ooz9T4Ag==" "integrity": "sha512-9oBGvXilL+/1tH5uVPo8rFlUbQP05n9hdj85YFvGAwjH1NP/bRSYhHcywkBe8aFFmkQHr3oi0Creh5ooz9T4Ag=="
}, },
"node_modules/bootstrap5-tags": { "node_modules/bootstrap5-tags": {
"version": "1.7.2", "version": "1.7.4",
"resolved": "https://registry.npmjs.org/bootstrap5-tags/-/bootstrap5-tags-1.7.2.tgz", "resolved": "https://registry.npmjs.org/bootstrap5-tags/-/bootstrap5-tags-1.7.4.tgz",
"integrity": "sha512-i4XksM6bhZGHlXnnTlwM7HMM549/eUsTsXvptFrbn2JlCHeIi4yFdL0NHP5pRw4eg4e33Girp9iIWqd2KN8DTA==" "integrity": "sha512-eQWu6/EHGf45R8EFdTCk8JQeY5oqfvQvEaYNZmFttnN56YOFpD7U+S5snEngsxZArwj57BLa9Yf0/QOggXJhcg=="
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
@@ -3888,9 +3891,9 @@
} }
}, },
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.23.2", "version": "4.23.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
"integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -3907,9 +3910,9 @@
} }
], ],
"dependencies": { "dependencies": {
"caniuse-lite": "^1.0.30001640", "caniuse-lite": "^1.0.30001646",
"electron-to-chromium": "^1.4.820", "electron-to-chromium": "^1.5.4",
"node-releases": "^2.0.14", "node-releases": "^2.0.18",
"update-browserslist-db": "^1.1.0" "update-browserslist-db": "^1.1.0"
}, },
"bin": { "bin": {
@@ -4008,9 +4011,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001643", "version": "1.0.30001647",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001647.tgz",
"integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", "integrity": "sha512-n83xdNiyeNcHpzWY+1aFbqCK7LuLfBricc4+alSQL2Xb6OR3XpnQAmlDG+pQcdTfiHRuLcQ96VOfrPSGiNJYSg==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -4417,12 +4420,12 @@
"dev": true "dev": true
}, },
"node_modules/core-js-compat": { "node_modules/core-js-compat": {
"version": "3.37.1", "version": "3.38.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz",
"integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", "integrity": "sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"browserslist": "^4.23.0" "browserslist": "^4.23.3"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@@ -5083,9 +5086,9 @@
"dev": true "dev": true
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.2", "version": "1.5.4",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.2.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz",
"integrity": "sha512-kc4r3U3V3WLaaZqThjYz/Y6z8tJe+7K0bbjUVo3i+LWIypVdMx5nXCkwRe6SWbY6ILqLdc1rKcKmr3HoH7wjSQ==", "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==",
"dev": true "dev": true
}, },
"node_modules/elliptic": { "node_modules/elliptic": {
@@ -7070,12 +7073,12 @@
} }
}, },
"node_modules/magic-string": { "node_modules/magic-string": {
"version": "0.30.10", "version": "0.30.11",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz",
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15" "@jridgewell/sourcemap-codec": "^1.5.0"
} }
}, },
"node_modules/make-dir": { "node_modules/make-dir": {
@@ -8643,9 +8646,9 @@
"dev": true "dev": true
}, },
"node_modules/qs": { "node_modules/qs": {
"version": "6.12.3", "version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"side-channel": "^1.0.6" "side-channel": "^1.0.6"
@@ -8994,9 +8997,9 @@
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.19.1", "version": "4.20.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.19.1.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.20.0.tgz",
"integrity": "sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==", "integrity": "sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/estree": "1.0.5" "@types/estree": "1.0.5"
@@ -9009,22 +9012,22 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.19.1", "@rollup/rollup-android-arm-eabi": "4.20.0",
"@rollup/rollup-android-arm64": "4.19.1", "@rollup/rollup-android-arm64": "4.20.0",
"@rollup/rollup-darwin-arm64": "4.19.1", "@rollup/rollup-darwin-arm64": "4.20.0",
"@rollup/rollup-darwin-x64": "4.19.1", "@rollup/rollup-darwin-x64": "4.20.0",
"@rollup/rollup-linux-arm-gnueabihf": "4.19.1", "@rollup/rollup-linux-arm-gnueabihf": "4.20.0",
"@rollup/rollup-linux-arm-musleabihf": "4.19.1", "@rollup/rollup-linux-arm-musleabihf": "4.20.0",
"@rollup/rollup-linux-arm64-gnu": "4.19.1", "@rollup/rollup-linux-arm64-gnu": "4.20.0",
"@rollup/rollup-linux-arm64-musl": "4.19.1", "@rollup/rollup-linux-arm64-musl": "4.20.0",
"@rollup/rollup-linux-powerpc64le-gnu": "4.19.1", "@rollup/rollup-linux-powerpc64le-gnu": "4.20.0",
"@rollup/rollup-linux-riscv64-gnu": "4.19.1", "@rollup/rollup-linux-riscv64-gnu": "4.20.0",
"@rollup/rollup-linux-s390x-gnu": "4.19.1", "@rollup/rollup-linux-s390x-gnu": "4.20.0",
"@rollup/rollup-linux-x64-gnu": "4.19.1", "@rollup/rollup-linux-x64-gnu": "4.20.0",
"@rollup/rollup-linux-x64-musl": "4.19.1", "@rollup/rollup-linux-x64-musl": "4.20.0",
"@rollup/rollup-win32-arm64-msvc": "4.19.1", "@rollup/rollup-win32-arm64-msvc": "4.20.0",
"@rollup/rollup-win32-ia32-msvc": "4.19.1", "@rollup/rollup-win32-ia32-msvc": "4.20.0",
"@rollup/rollup-win32-x64-msvc": "4.19.1", "@rollup/rollup-win32-x64-msvc": "4.20.0",
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
@@ -9903,9 +9906,9 @@
} }
}, },
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "6.11.1", "version": "6.13.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.11.1.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz",
"integrity": "sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==", "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==",
"dev": true "dev": true
}, },
"node_modules/unicode-canonical-property-names-ecmascript": { "node_modules/unicode-canonical-property-names-ecmascript": {