Compare commits

..

12 Commits

Author SHA1 Message Date
github-actions[bot]
1add505644 Merge pull request #10634 from firefly-iii/release-1753068994
🤖 Automatically merge the PR into the develop branch.
2025-07-21 05:36:42 +02:00
JC5
9663eb6a19 🤖 Auto commit for release 'develop' on 2025-07-21 2025-07-21 05:36:34 +02:00
github-actions[bot]
f30a24a02f Merge pull request #10629 from firefly-iii/release-1753029916
🤖 Automatically merge the PR into the develop branch.
2025-07-20 18:45:22 +02:00
JC5
68655d60a6 🤖 Auto commit for release 'develop' on 2025-07-20 2025-07-20 18:45:16 +02:00
James Cole
63b0efcd81 Remove sonarcloud flow. 2025-07-20 18:41:05 +02:00
James Cole
93284682c8 Improve bill overview. 2025-07-20 14:02:53 +02:00
github-actions[bot]
3bafcb6ad2 Merge pull request #10625 from firefly-iii/release-1753007822
🤖 Automatically merge the PR into the develop branch.
2025-07-20 12:37:09 +02:00
JC5
942d027556 🤖 Auto commit for release 'develop' on 2025-07-20 2025-07-20 12:37:02 +02:00
James Cole
a60882d5f5 Clean up v2. 2025-07-20 12:32:53 +02:00
James Cole
680f554981 Fix #10618 2025-07-19 21:08:37 +02:00
James Cole
20e4dc07ce Bad quote in html 2025-07-18 19:53:22 +02:00
James Cole
184d8eb027 Use new settings for php cs fixer. 2025-07-17 06:54:20 +02:00
20 changed files with 337 additions and 358 deletions

View File

@@ -33,6 +33,7 @@ $finder = PhpCsFixer\Finder::create()
$config = (new PhpCsFixer\Config())
// ->setUnsupportedPhpVersionAllowed(true) // use this when PHP 8.5 comes out.
->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect())
;
return $config->setRules(

View File

@@ -26,7 +26,7 @@ SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
cd $SCRIPT_DIR/php-cs-fixer
composer update --quiet
rm -f .php-cs-fixer.cache
PHP_CS_FIXER_IGNORE_ENV=true ./vendor/bin/php-cs-fixer fix \
./vendor/bin/php-cs-fixer fix \
--config $SCRIPT_DIR/php-cs-fixer/.php-cs-fixer.php \
--format=txt \
-v \

View File

@@ -1,71 +0,0 @@
name: 'Code - Run Sonarcloud'
on:
pull_request:
workflow_dispatch:
push:
branches:
- main
env:
DB_CONNECTION: sqlite
APP_KEY: TestTestTestTestTestTestTestTest
jobs:
sonarcloud:
name: SonarCloud
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP with Xdebug
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
coverage: xdebug
extensions: >-
bcmath
curl
fileinfo
iconv
intl
json
sqlite3
mbstring
openssl
pdo
session
simplexml
sodium
tokenizer
xml
xmlwriter
- name: Copy standard configuration
run: cp .env.testing .env
- name: Install Composer dependencies
run: composer install --prefer-dist --no-interaction --no-progress --no-scripts
- name: "Create database file"
run: |
touch storage/database/database.sqlite
wget -q https://github.com/firefly-iii/test-fixtures/raw/refs/heads/main/test-database.sqlite -O storage/database/database.sqlite
- name: "Upgrades the database to the latest version"
run: |
php artisan firefly-iii:upgrade-database
chmod 600 storage/oauth-public.key
chmod 600 storage/oauth-private.key
- name: "Integrity Database Report"
run: php artisan firefly-iii:report-integrity
- name: "Run tests with coverage"
run: composer coverage
- name: Fix code coverage paths
run: sed -i 's@'$GITHUB_WORKSPACE'@/github/workspace/@g' coverage.xml
- name: SonarCloud Scan
uses: SonarSource/sonarqube-scan-action@v5.2.0
env:
GITHUB_TOKEN: ${{ secrets.GH_ACTIONS_PERSONAL_ACCESS_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

View File

@@ -88,7 +88,9 @@ class IndexController extends Controller
/** @var Carbon $end */
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
$start->subDay();
// #10618 go to the end of the previous day.
$start->subSecond();
$ids = $accounts->pluck('id')->toArray();
Log::debug(sprintf('inactive start: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));
@@ -164,8 +166,8 @@ class IndexController extends Controller
/** @var Carbon $end */
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
// 2025-05-11 removed this so start is exactly the start of the month.
// $start->subDay();
// #10618 go to the end of the previous day.
$start->subSecond();
$ids = $accounts->pluck('id')->toArray();
Log::debug(sprintf('index start: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));

View File

@@ -312,11 +312,23 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
Log::debug(sprintf('Search for linked journals between %s and %s', $start->toW3cString(), $end->toW3cString()));
return $bill->transactionJournals()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('transaction_currencies AS currency', 'currency.id', '=', 'transactions.transaction_currency_id')
->leftJoin('transaction_currencies AS foreign_currency', 'foreign_currency.id', '=', 'transactions.foreign_currency_id')
->where('transactions.amount', '>', 0)
->before($end)->after($start)->get(
[
'transaction_journals.id',
'transaction_journals.date',
'transaction_journals.transaction_group_id',
'transactions.transaction_currency_id',
'currency.code AS transaction_currency_code',
'currency.decimal_places AS transaction_currency_decimal_places',
'transactions.foreign_currency_id',
'foreign_currency.code AS foreign_currency_code',
'foreign_currency.decimal_places AS foreign_currency_decimal_places',
'transactions.amount',
'transactions.foreign_amount',
]
)
;

View File

@@ -32,8 +32,10 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Models\BillDateCalculator;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* Class BillTransformer
@@ -150,11 +152,11 @@ class BillTransformer extends AbstractTransformer
'id' => $bill->id,
'created_at' => $bill->created_at->toAtomString(),
'updated_at' => $bill->updated_at->toAtomString(),
'currency_id' => (string) $bill->transaction_currency_id,
'currency_id' => (string)$bill->transaction_currency_id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'native_currency_id' => null === $default ? null : (string) $default->id,
'native_currency_id' => null === $default ? null : (string)$default->id,
'native_currency_code' => $default?->code,
'native_currency_symbol' => $default?->symbol,
'native_currency_decimal_places' => $default?->decimal_places,
@@ -171,7 +173,7 @@ class BillTransformer extends AbstractTransformer
'active' => $bill->active,
'order' => $bill->order,
'notes' => $notes,
'object_group_id' => null !== $objectGroupId ? (string) $objectGroupId : null,
'object_group_id' => null !== $objectGroupId ? (string)$objectGroupId : null,
'object_group_order' => $objectGroupOrder,
'object_group_title' => $objectGroupTitle,
@@ -194,9 +196,9 @@ class BillTransformer extends AbstractTransformer
*/
protected function paidData(Bill $bill): array
{
app('log')->debug(sprintf('Now in paidData for bill #%d', $bill->id));
Log::debug(sprintf('Now in paidData for bill #%d', $bill->id));
if (null === $this->parameters->get('start') || null === $this->parameters->get('end')) {
app('log')->debug('parameters are NULL, return empty array');
Log::debug('parameters are NULL, return empty array');
return [];
}
@@ -217,27 +219,40 @@ class BillTransformer extends AbstractTransformer
$searchStart->startOfDay();
$searchEnd->endOfDay();
app('log')->debug(sprintf('Parameters are start: %s end: %s', $start->format('Y-m-d'), $end->format('Y-m-d')));
app('log')->debug(sprintf('Search parameters are: start: %s', $searchStart->format('Y-m-d')));
Log::debug(sprintf('Parameters are start: %s end: %s', $start->format('Y-m-d'), $end->format('Y-m-d')));
Log::debug(sprintf('Search parameters are: start: %s', $searchStart->format('Y-m-d')));
// Get from database when bill was paid.
$set = $this->repository->getPaidDatesInRange($bill, $searchStart, $searchEnd);
app('log')->debug(sprintf('Count %d entries in getPaidDatesInRange()', $set->count()));
Log::debug(sprintf('Count %d entries in getPaidDatesInRange()', $set->count()));
// Grab from array the most recent payment. If none exist, fall back to the start date and pretend *that* was the last paid date.
app('log')->debug(sprintf('Grab last paid date from function, return %s if it comes up with nothing.', $start->format('Y-m-d')));
Log::debug(sprintf('Grab last paid date from function, return %s if it comes up with nothing.', $start->format('Y-m-d')));
$lastPaidDate = $this->lastPaidDate($set, $start);
app('log')->debug(sprintf('Result of lastPaidDate is %s', $lastPaidDate->format('Y-m-d')));
Log::debug(sprintf('Result of lastPaidDate is %s', $lastPaidDate->format('Y-m-d')));
// At this point the "next match" is exactly after the last time the bill was paid.
$result = [];
foreach ($set as $entry) {
$result[] = [
'transaction_group_id' => (string) $entry->transaction_group_id,
'transaction_journal_id' => (string) $entry->id,
'date' => $entry->date->format('Y-m-d'),
'date_object' => $entry->date,
$array = [
'transaction_group_id' => (string)$entry->transaction_group_id,
'transaction_journal_id' => (string)$entry->id,
'date' => $entry->date->format('Y-m-d'),
'date_object' => $entry->date,
'currency_id' => $entry->transaction_currency_id,
'currency_code' => $entry->transaction_currency_code,
'currency_decimal_places' => $entry->transaction_currency_decimal_places,
'amount' => Steam::bcround($entry->amount, $entry->transaction_currency_decimal_places),
];
if (null !== $entry->foreign_amount && null !== $entry->foreign_currency_code) {
$array['foreign_currency_id'] = $entry->foreign_currency_id;
$array['foreign_currency_code'] = $entry->foreign_currency_code;
$array['foreign_currency_decimal_places'] = $entry->foreign_currency_decimal_places;
$array['foreign_amount'] = Steam::bcround($entry->foreign_amount, $entry->foreign_currency_decimal_places);
}
$result[] = $array;
}
return $result;
@@ -265,7 +280,7 @@ class BillTransformer extends AbstractTransformer
private function getLastPaidDate(array $paidData): ?Carbon
{
app('log')->debug('getLastPaidDate()');
Log::debug('getLastPaidDate()');
$return = null;
foreach ($paidData as $entry) {
if (null !== $return) {
@@ -274,15 +289,15 @@ class BillTransformer extends AbstractTransformer
if ($current->gt($return)) {
$return = clone $current;
}
app('log')->debug(sprintf('Last paid date is: %s', $return->format('Y-m-d')));
Log::debug(sprintf('Last paid date is: %s', $return->format('Y-m-d')));
}
if (null === $return) {
/** @var Carbon $return */
$return = $entry['date_object'];
app('log')->debug(sprintf('Last paid date is: %s', $return->format('Y-m-d')));
Log::debug(sprintf('Last paid date is: %s', $return->format('Y-m-d')));
}
}
app('log')->debug(sprintf('Last paid date is: "%s"', $return?->format('Y-m-d')));
Log::debug(sprintf('Last paid date is: "%s"', $return?->format('Y-m-d')));
return $return;
}

74
composer.lock generated
View File

@@ -2619,16 +2619,16 @@
},
{
"name": "league/commonmark",
"version": "2.7.0",
"version": "2.7.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
"reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405"
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
"reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca",
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca",
"shasum": ""
},
"require": {
@@ -2657,7 +2657,7 @@
"symfony/process": "^5.4 | ^6.0 | ^7.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
"unleashedtech/php-coding-standard": "^3.1.1",
"vimeo/psalm": "^4.24.0 || ^5.0.0"
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
},
"suggest": {
"symfony/yaml": "v2.3+ required if using the Front Matter extension"
@@ -2722,7 +2722,7 @@
"type": "tidelift"
}
],
"time": "2025-05-05T12:20:28+00:00"
"time": "2025-07-20T12:47:49+00:00"
},
{
"name": "league/config",
@@ -9925,20 +9925,20 @@
},
{
"name": "barryvdh/laravel-ide-helper",
"version": "v3.5.5",
"version": "v3.6.0",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-ide-helper.git",
"reference": "8d441ec99f8612b942b55f5183151d91591b618a"
"reference": "8d00250cba25728373e92c1d8dcebcbf64623d29"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/8d441ec99f8612b942b55f5183151d91591b618a",
"reference": "8d441ec99f8612b942b55f5183151d91591b618a",
"url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/8d00250cba25728373e92c1d8dcebcbf64623d29",
"reference": "8d00250cba25728373e92c1d8dcebcbf64623d29",
"shasum": ""
},
"require": {
"barryvdh/reflection-docblock": "^2.3",
"barryvdh/reflection-docblock": "^2.4",
"composer/class-map-generator": "^1.0",
"ext-json": "*",
"illuminate/console": "^11.15 || ^12",
@@ -10003,7 +10003,7 @@
],
"support": {
"issues": "https://github.com/barryvdh/laravel-ide-helper/issues",
"source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.5.5"
"source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.6.0"
},
"funding": [
{
@@ -10015,20 +10015,20 @@
"type": "github"
}
],
"time": "2025-02-11T13:59:46+00:00"
"time": "2025-07-17T20:11:57+00:00"
},
{
"name": "barryvdh/reflection-docblock",
"version": "v2.3.1",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/ReflectionDocBlock.git",
"reference": "b6ff9f93603561f50e53b64310495d20b8dff5d8"
"reference": "d103774cbe7e94ddee7e4870f97f727b43fe7201"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/b6ff9f93603561f50e53b64310495d20b8dff5d8",
"reference": "b6ff9f93603561f50e53b64310495d20b8dff5d8",
"url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/d103774cbe7e94ddee7e4870f97f727b43fe7201",
"reference": "d103774cbe7e94ddee7e4870f97f727b43fe7201",
"shasum": ""
},
"require": {
@@ -10065,9 +10065,9 @@
}
],
"support": {
"source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.3.1"
"source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.4.0"
},
"time": "2025-01-18T19:26:32+00:00"
"time": "2025-07-17T06:07:30+00:00"
},
{
"name": "cloudcreativity/json-api-testing",
@@ -10471,16 +10471,16 @@
},
{
"name": "larastan/larastan",
"version": "v3.5.0",
"version": "v3.6.0",
"source": {
"type": "git",
"url": "https://github.com/larastan/larastan.git",
"reference": "e8ccd73008487ba91da9877b373f8c447743f1ce"
"reference": "6431d010dd383a9279eb8874a76ddb571738564a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/larastan/larastan/zipball/e8ccd73008487ba91da9877b373f8c447743f1ce",
"reference": "e8ccd73008487ba91da9877b373f8c447743f1ce",
"url": "https://api.github.com/repos/larastan/larastan/zipball/6431d010dd383a9279eb8874a76ddb571738564a",
"reference": "6431d010dd383a9279eb8874a76ddb571738564a",
"shasum": ""
},
"require": {
@@ -10548,7 +10548,7 @@
],
"support": {
"issues": "https://github.com/larastan/larastan/issues",
"source": "https://github.com/larastan/larastan/tree/v3.5.0"
"source": "https://github.com/larastan/larastan/tree/v3.6.0"
},
"funding": [
{
@@ -10556,7 +10556,7 @@
"type": "github"
}
],
"time": "2025-06-19T22:41:50+00:00"
"time": "2025-07-11T06:52:52+00:00"
},
{
"name": "laravel-json-api/testing",
@@ -11062,16 +11062,16 @@
},
{
"name": "phpstan/phpstan",
"version": "2.1.17",
"version": "2.1.18",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "89b5ef665716fa2a52ecd2633f21007a6a349053"
"reference": "ee1f390b7a70cdf74a2b737e554f68afea885db7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053",
"reference": "89b5ef665716fa2a52ecd2633f21007a6a349053",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/ee1f390b7a70cdf74a2b737e554f68afea885db7",
"reference": "ee1f390b7a70cdf74a2b737e554f68afea885db7",
"shasum": ""
},
"require": {
@@ -11116,7 +11116,7 @@
"type": "github"
}
],
"time": "2025-05-21T20:55:28+00:00"
"time": "2025-07-17T17:22:31+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
@@ -11654,21 +11654,21 @@
},
{
"name": "rector/rector",
"version": "2.1.1",
"version": "2.1.2",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
"reference": "d0917c069bb0d9bb06ed111cf052510f609015a4"
"reference": "40a71441dd73fa150a66102f5ca1364c44fc8fff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/d0917c069bb0d9bb06ed111cf052510f609015a4",
"reference": "d0917c069bb0d9bb06ed111cf052510f609015a4",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/40a71441dd73fa150a66102f5ca1364c44fc8fff",
"reference": "40a71441dd73fa150a66102f5ca1364c44fc8fff",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0",
"phpstan/phpstan": "^2.1.17"
"phpstan/phpstan": "^2.1.18"
},
"conflict": {
"rector/rector-doctrine": "*",
@@ -11702,7 +11702,7 @@
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.1.1"
"source": "https://github.com/rectorphp/rector/tree/2.1.2"
},
"funding": [
{
@@ -11710,7 +11710,7 @@
"type": "github"
}
],
"time": "2025-07-10T11:31:31+00:00"
"time": "2025-07-17T19:30:06+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag.
],
'version' => '6.2.21',
'build_time' => 1752727463,
'version' => 'develop/2025-07-21',
'build_time' => 1753068886,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 26,

252
package-lock.json generated
View File

@@ -1700,9 +1700,9 @@
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.6.tgz",
"integrity": "sha512-ShbM/3XxwuxjFiuVBHA+d3j5dyac0aEVVq1oluIDf71hUw0aRF59dV/efUsIwFnR6m8JNM2FjZOzmaZ8yG61kw==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz",
"integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==",
"cpu": [
"ppc64"
],
@@ -1717,9 +1717,9 @@
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.6.tgz",
"integrity": "sha512-S8ToEOVfg++AU/bHwdksHNnyLyVM+eMVAOf6yRKFitnwnbwwPNqKr3srzFRe7nzV69RQKb5DgchIX5pt3L53xg==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz",
"integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==",
"cpu": [
"arm"
],
@@ -1734,9 +1734,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.6.tgz",
"integrity": "sha512-hd5zdUarsK6strW+3Wxi5qWws+rJhCCbMiC9QZyzoxfk5uHRIE8T287giQxzVpEvCwuJ9Qjg6bEjcRJcgfLqoA==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz",
"integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==",
"cpu": [
"arm64"
],
@@ -1751,9 +1751,9 @@
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.6.tgz",
"integrity": "sha512-0Z7KpHSr3VBIO9A/1wcT3NTy7EB4oNC4upJ5ye3R7taCc2GUdeynSLArnon5G8scPwaU866d3H4BCrE5xLW25A==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz",
"integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==",
"cpu": [
"x64"
],
@@ -1768,9 +1768,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.6.tgz",
"integrity": "sha512-FFCssz3XBavjxcFxKsGy2DYK5VSvJqa6y5HXljKzhRZ87LvEi13brPrf/wdyl/BbpbMKJNOr1Sd0jtW4Ge1pAA==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz",
"integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==",
"cpu": [
"arm64"
],
@@ -1785,9 +1785,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.6.tgz",
"integrity": "sha512-GfXs5kry/TkGM2vKqK2oyiLFygJRqKVhawu3+DOCk7OxLy/6jYkWXhlHwOoTb0WqGnWGAS7sooxbZowy+pK9Yg==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz",
"integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==",
"cpu": [
"x64"
],
@@ -1802,9 +1802,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.6.tgz",
"integrity": "sha512-aoLF2c3OvDn2XDTRvn8hN6DRzVVpDlj2B/F66clWd/FHLiHaG3aVZjxQX2DYphA5y/evbdGvC6Us13tvyt4pWg==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz",
"integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==",
"cpu": [
"arm64"
],
@@ -1819,9 +1819,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.6.tgz",
"integrity": "sha512-2SkqTjTSo2dYi/jzFbU9Plt1vk0+nNg8YC8rOXXea+iA3hfNJWebKYPs3xnOUf9+ZWhKAaxnQNUf2X9LOpeiMQ==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz",
"integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==",
"cpu": [
"x64"
],
@@ -1836,9 +1836,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.6.tgz",
"integrity": "sha512-SZHQlzvqv4Du5PrKE2faN0qlbsaW/3QQfUUc6yO2EjFcA83xnwm91UbEEVx4ApZ9Z5oG8Bxz4qPE+HFwtVcfyw==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz",
"integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==",
"cpu": [
"arm"
],
@@ -1853,9 +1853,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.6.tgz",
"integrity": "sha512-b967hU0gqKd9Drsh/UuAm21Khpoh6mPBSgz8mKRq4P5mVK8bpA+hQzmm/ZwGVULSNBzKdZPQBRT3+WuVavcWsQ==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz",
"integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==",
"cpu": [
"arm64"
],
@@ -1870,9 +1870,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.6.tgz",
"integrity": "sha512-aHWdQ2AAltRkLPOsKdi3xv0mZ8fUGPdlKEjIEhxCPm5yKEThcUjHpWB1idN74lfXGnZ5SULQSgtr5Qos5B0bPw==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz",
"integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==",
"cpu": [
"ia32"
],
@@ -1887,9 +1887,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.6.tgz",
"integrity": "sha512-VgKCsHdXRSQ7E1+QXGdRPlQ/e08bN6WMQb27/TMfV+vPjjTImuT9PmLXupRlC90S1JeNNW5lzkAEO/McKeJ2yg==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz",
"integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==",
"cpu": [
"loong64"
],
@@ -1904,9 +1904,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.6.tgz",
"integrity": "sha512-WViNlpivRKT9/py3kCmkHnn44GkGXVdXfdc4drNmRl15zVQ2+D2uFwdlGh6IuK5AAnGTo2qPB1Djppj+t78rzw==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz",
"integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==",
"cpu": [
"mips64el"
],
@@ -1921,9 +1921,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.6.tgz",
"integrity": "sha512-wyYKZ9NTdmAMb5730I38lBqVu6cKl4ZfYXIs31Baf8aoOtB4xSGi3THmDYt4BTFHk7/EcVixkOV2uZfwU3Q2Jw==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz",
"integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==",
"cpu": [
"ppc64"
],
@@ -1938,9 +1938,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.6.tgz",
"integrity": "sha512-KZh7bAGGcrinEj4qzilJ4hqTY3Dg2U82c8bv+e1xqNqZCrCyc+TL9AUEn5WGKDzm3CfC5RODE/qc96OcbIe33w==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz",
"integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==",
"cpu": [
"riscv64"
],
@@ -1955,9 +1955,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.6.tgz",
"integrity": "sha512-9N1LsTwAuE9oj6lHMyyAM+ucxGiVnEqUdp4v7IaMmrwb06ZTEVCIs3oPPplVsnjPfyjmxwHxHMF8b6vzUVAUGw==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz",
"integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==",
"cpu": [
"s390x"
],
@@ -1972,9 +1972,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.6.tgz",
"integrity": "sha512-A6bJB41b4lKFWRKNrWoP2LHsjVzNiaurf7wyj/XtFNTsnPuxwEBWHLty+ZE0dWBKuSK1fvKgrKaNjBS7qbFKig==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz",
"integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==",
"cpu": [
"x64"
],
@@ -1989,9 +1989,9 @@
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.6.tgz",
"integrity": "sha512-IjA+DcwoVpjEvyxZddDqBY+uJ2Snc6duLpjmkXm/v4xuS3H+3FkLZlDm9ZsAbF9rsfP3zeA0/ArNDORZgrxR/Q==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz",
"integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==",
"cpu": [
"arm64"
],
@@ -2006,9 +2006,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.6.tgz",
"integrity": "sha512-dUXuZr5WenIDlMHdMkvDc1FAu4xdWixTCRgP7RQLBOkkGgwuuzaGSYcOpW4jFxzpzL1ejb8yF620UxAqnBrR9g==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz",
"integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==",
"cpu": [
"x64"
],
@@ -2023,9 +2023,9 @@
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.6.tgz",
"integrity": "sha512-l8ZCvXP0tbTJ3iaqdNf3pjaOSd5ex/e6/omLIQCVBLmHTlfXW3zAxQ4fnDmPLOB1x9xrcSi/xtCWFwCZRIaEwg==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz",
"integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==",
"cpu": [
"arm64"
],
@@ -2040,9 +2040,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.6.tgz",
"integrity": "sha512-hKrmDa0aOFOr71KQ/19JC7az1P0GWtCN1t2ahYAf4O007DHZt/dW8ym5+CUdJhQ/qkZmI1HAF8KkJbEFtCL7gw==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz",
"integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==",
"cpu": [
"x64"
],
@@ -2057,9 +2057,9 @@
}
},
"node_modules/@esbuild/openharmony-arm64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.6.tgz",
"integrity": "sha512-+SqBcAWoB1fYKmpWoQP4pGtx+pUUC//RNYhFdbcSA16617cchuryuhOCRpPsjCblKukAckWsV+aQ3UKT/RMPcA==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz",
"integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==",
"cpu": [
"arm64"
],
@@ -2074,9 +2074,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.6.tgz",
"integrity": "sha512-dyCGxv1/Br7MiSC42qinGL8KkG4kX0pEsdb0+TKhmJZgCUDBGmyo1/ArCjNGiOLiIAgdbWgmWgib4HoCi5t7kA==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz",
"integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==",
"cpu": [
"x64"
],
@@ -2091,9 +2091,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.6.tgz",
"integrity": "sha512-42QOgcZeZOvXfsCBJF5Afw73t4veOId//XD3i+/9gSkhSV6Gk3VPlWncctI+JcOyERv85FUo7RxuxGy+z8A43Q==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz",
"integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==",
"cpu": [
"arm64"
],
@@ -2108,9 +2108,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.6.tgz",
"integrity": "sha512-4AWhgXmDuYN7rJI6ORB+uU9DHLq/erBbuMoAuB4VWJTu5KtCgcKYPynF0YI1VkBNuEfjNlLrFr9KZPJzrtLkrQ==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz",
"integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==",
"cpu": [
"ia32"
],
@@ -2125,9 +2125,9 @@
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.6.tgz",
"integrity": "sha512-NgJPHHbEpLQgDH2MjQu90pzW/5vvXIZ7KOnPyNBm92A6WgZ/7b6fJyUBjoumLqeOQQGqY2QjQxRo97ah4Sj0cA==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz",
"integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==",
"cpu": [
"x64"
],
@@ -3141,9 +3141,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.0.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.14.tgz",
"integrity": "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw==",
"version": "24.0.15",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.15.tgz",
"integrity": "sha512-oaeTSbCef7U/z7rDeJA138xpG3NuKc64/rZ2qmUFkFJmnMsAPaluIifqyWd8hSSMxyP9oie3dLAqYPblag9KgA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4766,9 +4766,9 @@
}
},
"node_modules/compression": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz",
"integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==",
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
"integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4776,7 +4776,7 @@
"compressible": "~2.0.18",
"debug": "2.6.9",
"negotiator": "~0.6.4",
"on-headers": "~1.0.2",
"on-headers": "~1.1.0",
"safe-buffer": "5.2.1",
"vary": "~1.1.2"
},
@@ -5694,9 +5694,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.186",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.186.tgz",
"integrity": "sha512-lur7L4BFklgepaJxj4DqPk7vKbTEl0pajNlg2QjE5shefmlmBLm2HvQ7PMf1R/GvlevT/581cop33/quQcfX3A==",
"version": "1.5.187",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.187.tgz",
"integrity": "sha512-cl5Jc9I0KGUoOoSbxvTywTa40uspGJt/BDBoDLoxJRSBpWh4FFXBsjNRHfQrONsV/OoEjDfHUmZQa2d6Ze4YgA==",
"dev": true,
"license": "ISC"
},
@@ -5857,9 +5857,9 @@
}
},
"node_modules/esbuild": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.6.tgz",
"integrity": "sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg==",
"version": "0.25.8",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz",
"integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -5870,32 +5870,32 @@
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.25.6",
"@esbuild/android-arm": "0.25.6",
"@esbuild/android-arm64": "0.25.6",
"@esbuild/android-x64": "0.25.6",
"@esbuild/darwin-arm64": "0.25.6",
"@esbuild/darwin-x64": "0.25.6",
"@esbuild/freebsd-arm64": "0.25.6",
"@esbuild/freebsd-x64": "0.25.6",
"@esbuild/linux-arm": "0.25.6",
"@esbuild/linux-arm64": "0.25.6",
"@esbuild/linux-ia32": "0.25.6",
"@esbuild/linux-loong64": "0.25.6",
"@esbuild/linux-mips64el": "0.25.6",
"@esbuild/linux-ppc64": "0.25.6",
"@esbuild/linux-riscv64": "0.25.6",
"@esbuild/linux-s390x": "0.25.6",
"@esbuild/linux-x64": "0.25.6",
"@esbuild/netbsd-arm64": "0.25.6",
"@esbuild/netbsd-x64": "0.25.6",
"@esbuild/openbsd-arm64": "0.25.6",
"@esbuild/openbsd-x64": "0.25.6",
"@esbuild/openharmony-arm64": "0.25.6",
"@esbuild/sunos-x64": "0.25.6",
"@esbuild/win32-arm64": "0.25.6",
"@esbuild/win32-ia32": "0.25.6",
"@esbuild/win32-x64": "0.25.6"
"@esbuild/aix-ppc64": "0.25.8",
"@esbuild/android-arm": "0.25.8",
"@esbuild/android-arm64": "0.25.8",
"@esbuild/android-x64": "0.25.8",
"@esbuild/darwin-arm64": "0.25.8",
"@esbuild/darwin-x64": "0.25.8",
"@esbuild/freebsd-arm64": "0.25.8",
"@esbuild/freebsd-x64": "0.25.8",
"@esbuild/linux-arm": "0.25.8",
"@esbuild/linux-arm64": "0.25.8",
"@esbuild/linux-ia32": "0.25.8",
"@esbuild/linux-loong64": "0.25.8",
"@esbuild/linux-mips64el": "0.25.8",
"@esbuild/linux-ppc64": "0.25.8",
"@esbuild/linux-riscv64": "0.25.8",
"@esbuild/linux-s390x": "0.25.8",
"@esbuild/linux-x64": "0.25.8",
"@esbuild/netbsd-arm64": "0.25.8",
"@esbuild/netbsd-x64": "0.25.8",
"@esbuild/openbsd-arm64": "0.25.8",
"@esbuild/openbsd-x64": "0.25.8",
"@esbuild/openharmony-arm64": "0.25.8",
"@esbuild/sunos-x64": "0.25.8",
"@esbuild/win32-arm64": "0.25.8",
"@esbuild/win32-ia32": "0.25.8",
"@esbuild/win32-x64": "0.25.8"
}
},
"node_modules/escalade": {
@@ -6401,9 +6401,9 @@
}
},
"node_modules/form-data": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz",
"integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6467,9 +6467,9 @@
}
},
"node_modules/fs-monkey": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz",
"integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz",
"integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==",
"dev": true,
"license": "Unlicense"
},
@@ -8552,9 +8552,9 @@
}
},
"node_modules/on-headers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
"integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
"dev": true,
"license": "MIT",
"engines": {

View File

@@ -48,6 +48,10 @@ window.bootstrap = bootstrap;
// always grab the preference "marker" from Firefly III.
getFreshVariable('lastActivity').then((serverValue) => {
if(null === serverValue) {
console.log('Server value is null in getFreshVariable.');
throw new Error('401 in getFreshVariable.');
}
const localValue = store.get('lastActivity');
store.set('cacheValid', localValue === serverValue);
store.set('lastActivity', serverValue);
@@ -78,6 +82,8 @@ getFreshVariable('lastActivity').then((serverValue) => {
window.bootstrapped = true;
});
});
}).catch((error) => {
console.error('Error while bootstrapping: ' + error);
});
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

View File

@@ -30,3 +30,4 @@
border:0;
}
.skip-links {display: none;}

View File

@@ -31,6 +31,71 @@ let afterPromises = false;
let apiData = [];
let subscriptionData = {};
function addObjectGroupInfo(data) {
let objectGroupId = parseInt(data.object_group_id);
if (!subscriptionData.hasOwnProperty(objectGroupId)) {
subscriptionData[objectGroupId] = {
id: objectGroupId,
title: null === data.object_group_title ? i18next.t('firefly.default_group_title_name_plain') : data.object_group_title,
order: parseInt(data.object_group_order),
payment_info: {},
bills: [],
};
}
}
function parseBillInfo(data) {
let result = {
id: data.id,
name: data.attributes.name,
amount_min: data.attributes.amount_min,
amount_max: data.attributes.amount_max,
amount: (parseFloat(data.attributes.amount_max) + parseFloat(data.attributes.amount_min)) / 2,
currency_code: data.attributes.currency_code,
// paid transactions:
transactions: [],
// unpaid moments
pay_dates: data.attributes.pay_dates,
paid: data.attributes.paid_dates.length > 0,
};
// set variables
result.expected_amount = formatMoney(result.amount, result.currency_code);
result.expected_times = i18next.t('firefly.subscr_expected_x_times', {
times: data.attributes.pay_dates.length,
amount: result.expected_amount
});
return result;
}
function parsePaidTransactions(paid_dates, bill) {
if( !paid_dates || paid_dates.length < 1) {
return [];
}
let result = [];
// add transactions (simpler version)
for (let i in paid_dates) {
if (paid_dates.hasOwnProperty(i)) {
const currentPayment = paid_dates[i];
console.log(currentPayment);
// math: -100+(paid/expected)*100
let percentage = Math.round(-100 + ((parseFloat(currentPayment.amount) ) / parseFloat(bill.amount)) * 100);
let currentTransaction = {
amount: formatMoney(currentPayment.amount, currentPayment.currency_code),
percentage: percentage,
date: format(new Date(currentPayment.date), 'PP'),
foreign_amount: null,
};
if (null !== currentPayment.foreign_currency_code) {
currentTransaction.foreign_amount = currentPayment.foreign_amount;
currentTransaction.foreign_currency_code = currentPayment.foreign_currency_code;
}
result.push(currentTransaction);
}
}
return result;
}
function downloadSubscriptions(params) {
const getter = new Get();
return getter.list(params)
@@ -41,80 +106,14 @@ function downloadSubscriptions(params) {
for (let i in data) {
if (data.hasOwnProperty(i)) {
let current = data[i];
//console.log(current);
if (current.attributes.active && current.attributes.pay_dates.length > 0) {
let objectGroupId = null === current.attributes.object_group_id ? 0 : current.attributes.object_group_id;
let objectGroupTitle = null === current.attributes.object_group_title ? i18next.t('firefly.default_group_title_name_plain') : current.attributes.object_group_title;
let objectGroupOrder = null === current.attributes.object_group_order ? 0 : current.attributes.object_group_order;
if (!subscriptionData.hasOwnProperty(objectGroupId)) {
subscriptionData[objectGroupId] = {
id: objectGroupId,
title: objectGroupTitle,
order: objectGroupOrder,
payment_info: {},
bills: [],
};
}
// TODO this conversion needs to be inside some kind of a parsing class.
let bill = {
id: current.id,
name: current.attributes.name,
// amount
amount_min: current.attributes.amount_min,
amount_max: current.attributes.amount_max,
amount: (parseFloat(current.attributes.amount_max) + parseFloat(current.attributes.amount_min)) / 2,
currency_code: current.attributes.currency_code,
// create or update object group
let objectGroupId = parseInt(current.attributes.object_group_id);
addObjectGroupInfo(current.attributes);
// native amount
// native_amount_min: current.attributes.native_amount_min,
// native_amount_max: current.attributes.native_amount_max,
// native_amount: (parseFloat(current.attributes.native_amount_max) + parseFloat(current.attributes.native_amount_min)) / 2,
// native_currency_code: current.attributes.native_currency_code,
// paid transactions:
transactions: [],
// unpaid moments
pay_dates: current.attributes.pay_dates,
paid: current.attributes.paid_dates.length > 0,
};
// set variables
bill.expected_amount = formatMoney(bill.amount, bill.currency_code);
bill.expected_times = i18next.t('firefly.subscr_expected_x_times', {
times: current.attributes.pay_dates.length,
amount: bill.expected_amount
});
// add transactions (simpler version)
for (let iii in current.attributes.paid_dates) {
if (current.attributes.paid_dates.hasOwnProperty(iii)) {
const currentPayment = current.attributes.paid_dates[iii];
let percentage = 100;
// math: -100+(paid/expected)*100
if (params.convertToNative) {
percentage = Math.round(-100 + ((parseFloat(currentPayment.native_amount) * -1) / parseFloat(bill.native_amount)) * 100);
}
if (!params.convertToNative) {
percentage = Math.round(-100 + ((parseFloat(currentPayment.amount) * -1) / parseFloat(bill.amount)) * 100);
}
// TODO fix me
currentPayment.currency_code = 'EUR';
console.log('Currency code: "'+currentPayment+'"');
console.log(currentPayment);
let currentTransaction = {
amount: formatMoney(currentPayment.amount, currentPayment.currency_code),
percentage: percentage,
date: format(new Date(currentPayment.date), 'PP'),
foreign_amount: null,
};
if (null !== currentPayment.foreign_currency_code) {
currentTransaction.foreign_amount = currentPayment.foreign_amount;
currentTransaction.foreign_currency_code = currentPayment.foreign_currency_code;
}
bill.transactions.push(currentTransaction);
}
}
// create and update the bill.
let bill = parseBillInfo(current);
bill.transactions = parsePaidTransactions(current.attributes.paid_dates, bill);
subscriptionData[objectGroupId].bills.push(bill);
if (0 === current.attributes.paid_dates.length) {

View File

@@ -1,5 +1,5 @@
/*!
* adminlte-filteres.scss
* adminlte-filtered.scss
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -23,7 +23,7 @@
// copied from:
/*!
* AdminLTE v4.0.0-alpha2
* AdminLTE v4.0.0-rc3
* Author: Colorlib
* Website: AdminLTE.io <https://adminlte.io>
* License: Open source - MIT <https://opensource.org/licenses/MIT>
@@ -84,7 +84,6 @@
// Bootstrap Utilities
@import "bootstrap/scss/utilities/api";
// AdminLTE Configuration
// ---------------------------------------------------
@import "admin-lte/src/scss/variables";
@@ -97,9 +96,12 @@
@import "admin-lte/src/scss/parts/components";
@import "admin-lte/src/scss/parts/extra-components";
// @import "admin-lte/src/scss/parts/pages";
@import "admin-lte/src/scss/pages/login_and_register";
//
// Part: Pages
//
@import "admin-lte/src/scss/pages/login_and_register";
@import "admin-lte/src/scss/parts/miscellaneous";
// AdminLTE Accessibility Styles - WCAG 2.1 AA Compliance
@import "admin-lte/src/scss/accessibility";

View File

@@ -26,6 +26,9 @@ $danger: #CD5029 !default;
$primary: #1E6581 !default;
$success: #64B624 !default;
.skip-links {display: none;}
/*
Remove bottom margin from unstyled lists
*/

View File

@@ -26,13 +26,17 @@ export function getFreshVariable(name, defaultValue = null) {
return getter.getByName(name).then((response) => {
// console.log('Get from API');
return Promise.resolve(parseResponse(name, response));
}).catch(() => {
// preference does not exist (yet).
// POST it and then return it anyway.
let poster = (new Post);
poster.post(name, defaultValue).then((response) => {
return Promise.resolve(parseResponse(name, response));
});
}).catch((response) => {
if(response.status === 404) {
// preference does not exist (yet).
// POST it and then return it anyway.
let poster = (new Post);
poster.post(name, defaultValue).then((response) => {
return Promise.resolve(parseResponse(name, response));
});
return;
}
return Promise.resolve(null);
});
}

View File

@@ -21,5 +21,9 @@
export function showInternalsButton() {
// console.log('showInternalsButton');
document.querySelector('.toggle-page-internals').classList.remove('d-none');
let obj = document.querySelector('.toggle-page-internals');
if (obj === null) {
return;
}
obj.classList.remove('d-none');
}

View File

@@ -83,7 +83,8 @@ export default defineConfig(({command, mode, isSsrBuild, isPreview}) => {
server: {
cors: true,
origin: 'https://192.168.96.154:5173',
// make sure this IP matches the IP of the dev machine.
origin: 'https://192.168.96.162:5173',
watch: {
usePolling: true,
},

View File

@@ -1866,8 +1866,8 @@ return [
'skip_help_text' => 'Use the skip field to create bi-monthly (skip = 1) or other custom intervals.',
'subscription' => 'Subscription',
'not_expected_period' => 'Not expected this period',
'subscriptions_in_group' => 'Subscriptions in group "%{title}"',
'subscr_expected_x_times' => 'Expect to pay %{amount} %{times} times this period',
'subscriptions_in_group' => 'Subscriptions in group "{{title}}"',
'subscr_expected_x_times' => 'Expect to pay {{amount}} {{times}} times this period',
'not_or_not_yet' => 'Not (yet)',
'visit_bill' => 'Visit subscription ":name" at Firefly III',
'match_between_amounts' => 'Subscription matches transactions between :low and :high.',

View File

@@ -29,7 +29,7 @@
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="invite_code" value="{{ $inviteCode ?? '' }}">
<div class="input-group mb-3">
<input type="email" name="email" autofocus required value="{{ $email }}" class="form-control" "
<input type="email" name="email" autofocus required value="{{ $email }}" class="form-control"
placeholder="{{ trans('form.email') }}"/>
<div class="input-group-text"> <em class="fa-solid fa-envelope"></em> </div>
</div>

View File

@@ -2,7 +2,7 @@
<div class="col-xl-3 col-lg-6 col-md-12 col-sm-12">
<div class="small-box text-bg-primary">
<div class="inner balance-box">
<h3 class="hover-expand">
<h4 class="hover-expand">
<template x-if="0 === balanceBox.amounts.length">
<span>&nbsp;</span>
</template>
@@ -12,7 +12,7 @@
:class="{ 'invisible': (balanceBox.amounts.length == index+1) }">, </span>
</span>
</template>
</h3>
</h4>
<template x-if="loading">
<p class="d-none d-xs-block">
<em class="fa-solid fa-spinner fa-spin"></em>
@@ -53,17 +53,17 @@
<div class="small-box text-bg-success">
<div class="inner">
<template x-if="0 === billBox.unpaid.length">
<h3>&nbsp;</h3>
<h4>&nbsp;</h4>
</template>
<template x-if="billBox.unpaid.length > 0">
<h3 class="hover-expand">
<h4 class="hover-expand">
<template x-for="(amount, index) in billBox.unpaid" :key="index">
<span>
<span x-text="amount"></span><span
:class="{ 'invisible': (billBox.unpaid.length == index+1) }">, </span>
</span>
</template>
</h3>
</h4>
</template>
<template x-if="loading">
<p class="d-none d-sm-block">
@@ -104,7 +104,7 @@
<!--begin::Small Box Widget 3-->
<div class="small-box text-bg-warning">
<div class="inner">
<h3 class="hover-expand">
<h4 class="hover-expand">
<template x-if="0 === leftBox.left.length">
<span>&nbsp;</span>
</template>
@@ -114,7 +114,7 @@
:class="{ 'invisible': (leftBox.left.length == index+1) }">, </span>
</span>
</template>
</h3>
</h4>
<template x-if="loading">
<p class="d-none d-sm-block">
@@ -153,14 +153,14 @@
<!--begin::Small Box Widget 4-->
<div class="small-box text-bg-danger">
<div class="inner">
<h3 class="hover-expand">
<h4 class="hover-expand">
<template x-for="(amount, index) in netBox.net" :key="index">
<span>
<span x-text="amount"></span><span
:class="{ 'invisible': (netBox.net.length == index+1) }">, </span>
</span>
</template>
</h3>
</h4>
<template x-if="loading">
<p class="d-none d-sm-block">